<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Donato Riccio</title>
    <description>The latest articles on DEV Community by Donato Riccio (@donnierich).</description>
    <link>https://dev.to/donnierich</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1091703%2F6c94d346-b56e-4ee5-a584-b9ca488b2472.png</url>
      <title>DEV Community: Donato Riccio</title>
      <link>https://dev.to/donnierich</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/donnierich"/>
    <language>en</language>
    <item>
      <title>Create your custom npm template package</title>
      <dc:creator>Donato Riccio</dc:creator>
      <pubDate>Mon, 10 Mar 2025 19:41:58 +0000</pubDate>
      <link>https://dev.to/donnierich/create-your-custom-npm-template-package-1ai5</link>
      <guid>https://dev.to/donnierich/create-your-custom-npm-template-package-1ai5</guid>
      <description>&lt;h5&gt;
  
  
  a.k.a what &lt;code&gt;npm create vite@latest&lt;/code&gt; does
&lt;/h5&gt;

&lt;h2&gt;
  
  
  Table of Contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;What we want&lt;/li&gt;
&lt;li&gt;
Before you continue

&lt;ul&gt;
&lt;li&gt;Try the package&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;The easiest way (template repository)&lt;/li&gt;

&lt;li&gt;

The npm create way

&lt;ul&gt;
&lt;li&gt;The npm create command&lt;/li&gt;
&lt;li&gt;
Package requirements

&lt;ul&gt;
&lt;li&gt;main / exports&lt;/li&gt;
&lt;li&gt;bin&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

A really basic package

&lt;ul&gt;
&lt;li&gt;&lt;a href="//#a-simple-console.log"&gt;A simple console.log&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Make the package available globally in your local machine&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;How to manage a more complex scaffolding&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;

A simple scaffolding package

&lt;ul&gt;
&lt;li&gt;Create a new project&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;A crossroad&lt;/li&gt;

&lt;li&gt;One package, many files&lt;/li&gt;

&lt;li&gt;

One package, many repos

&lt;ul&gt;
&lt;li&gt;A new old repo&lt;/li&gt;
&lt;li&gt;How to interact with the user and install the starter kit&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Conclusion&lt;/li&gt;

&lt;li&gt;Resources&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  What we want
&lt;/h2&gt;

&lt;p&gt;We want custom scaffolding to reduce the time needed to start a new project.&lt;br&gt;
Just think about it: how often do you take the same three, four, or five steps to start a project?&lt;br&gt;
Let's use Vue as an example:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;install Vue&lt;/li&gt;
&lt;li&gt;select maybe the extra packages (Vitest, Vue Router, Pinia)&lt;/li&gt;
&lt;li&gt;add Bootstrap (or Tailwind)&lt;/li&gt;
&lt;li&gt;add Sass&lt;/li&gt;
&lt;li&gt;add Vuex (if you don't want Pinia)&lt;/li&gt;
&lt;li&gt;add the simple state management (if you don't want Vuex)&lt;/li&gt;
&lt;li&gt;remove unwanted components&lt;/li&gt;
&lt;li&gt;add some basic components (i.e. HomePage for Vue Router)&lt;/li&gt;
&lt;li&gt;setup Vue Router&lt;/li&gt;
&lt;li&gt;and so on...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of repeating all these steps every time, we want a way to have all of them already done on any new project!&lt;br&gt;
Even more: we want the ability to keep our scaffolding updated in time.&lt;/p&gt;

&lt;p&gt;How can we do this?&lt;/p&gt;
&lt;h2&gt;
  
  
  Before you continue
&lt;/h2&gt;

&lt;p&gt;This tutorial is not a step-by-step guide on how to achieve the desired result. Is more of a: we can do things this way, it's possible and not so hard.&lt;br&gt;
The code is publicly available on GitHub and also are the npm packages. Even more: try the packages before you dive into the tutorial.&lt;/p&gt;

&lt;p&gt;See if this way of doing things is what you are looking for and only in this case keep reading the tutorial.&lt;br&gt;
Just remember this is not a tutorial on how to do everything. I firmly believe that in some cases is better to learn things "the hard way" rather than have everything handed to you.&lt;/p&gt;

&lt;p&gt;Try to make things work, struggle with Node errors, bash your head against the monitor, and close the day with at least a 1% of new things learned.&lt;/p&gt;
&lt;h3&gt;
  
  
  Try the package
&lt;/h3&gt;

&lt;p&gt;Run this command to install a new VueJS customized template for your project:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm create @ricciodev/templar@latest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The easiest way (template repository)
&lt;/h2&gt;

&lt;p&gt;One way to achieve the desired result is to create a GitHub repository and mark that repository as a &lt;code&gt;template repository&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;We can do this from the tab &lt;em&gt;Settings&lt;/em&gt;, right under the repository name.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F12smtni7f88wnfyltsdn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F12smtni7f88wnfyltsdn.png" alt=" " width="796" height="185"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we can create a new repository on GitHub from this template repository. This means the new repository will have all the files included in the template, right from the start.&lt;/p&gt;

&lt;p&gt;This is the easiest way to have a basic scaffolding ready to use.&lt;br&gt;
The &lt;em&gt;pros&lt;/em&gt; are: easy to do, and easy to maintain/update.&lt;br&gt;
The &lt;em&gt;cons&lt;/em&gt; are: if we need more than a couple of different scaffoldings, it becomes a bit hard to manage.&lt;/p&gt;

&lt;p&gt;Of course, we can push things further!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE&lt;br&gt;
We will come back to this method later.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  The &lt;code&gt;npm create&lt;/code&gt; way
&lt;/h2&gt;

&lt;p&gt;&lt;em&gt;aka what Vite does&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;We can create a npm package with the sole purpose of generating a project already structured with all the files and dependencies we need.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Vite&lt;/strong&gt; do this. &lt;strong&gt;Vue&lt;/strong&gt; does this. &lt;strong&gt;Astro&lt;/strong&gt; does this, and so on... the point being: that we already used this approach.&lt;br&gt;
Now is the time to make our own package!&lt;/p&gt;

&lt;p&gt;Before we start, we'll need just a bit of context.&lt;/p&gt;
&lt;h3&gt;
  
  
  The npm create command
&lt;/h3&gt;

&lt;p&gt;The &lt;code&gt;npm create &amp;lt;package-spec&amp;gt;&lt;/code&gt; command is only an alias for &lt;code&gt;npm init &amp;lt;package-spec&amp;gt;&lt;/code&gt;.&lt;br&gt;
All the information we need is available in the &lt;a href="https://docs.npmjs.com/cli/v10/commands/npm-init" rel="noopener noreferrer"&gt;npm documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To sum it up we quote the first paragraph of the &lt;code&gt;npm init&lt;/code&gt; documentation page:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;code&gt;npm init &amp;lt;initializer&amp;gt;&lt;/code&gt; can be used to set up a new or existing npm package.&lt;br&gt;
&lt;code&gt;initializer&lt;/code&gt; in this case is an npm package named &lt;code&gt;create-&amp;lt;initializer&amp;gt;&lt;/code&gt;, which will be installed by &lt;a href="https://docs.npmjs.com/cli/v10/commands/npm-exec" rel="noopener noreferrer"&gt;&lt;code&gt;npm-exec&lt;/code&gt;&lt;/a&gt;, and then have its main bin executed -- presumably creating or updating &lt;code&gt;package.json&lt;/code&gt; and running any other initialization-related operations.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This means our package name will be prefixed with &lt;code&gt;create-&lt;/code&gt;.&lt;br&gt;
I.E. &lt;code&gt;create-scaffolding-vue&lt;/code&gt;, &lt;code&gt;create-custom-react&lt;/code&gt; or to make everything even more organized we could publish our package under a scope to avoid naming conflicts (&lt;code&gt;@myorganization/create-react&lt;/code&gt;.)&lt;/p&gt;
&lt;h3&gt;
  
  
  Package requirements
&lt;/h3&gt;

&lt;p&gt;We need to define some options in the &lt;code&gt;package.json&lt;/code&gt; file.&lt;/p&gt;
&lt;h4&gt;
  
  
  main / exports
&lt;/h4&gt;

&lt;p&gt;First, we set the entry point using the &lt;code&gt;main&lt;/code&gt; key. The value will be the path to our main file (usually &lt;code&gt;index.js&lt;/code&gt;.)&lt;br&gt;
Later in this tutorial, we will drop &lt;code&gt;main&lt;/code&gt; and use the &lt;code&gt;exports&lt;/code&gt; field.&lt;/p&gt;
&lt;h4&gt;
  
  
  bin
&lt;/h4&gt;

&lt;p&gt;We also want to define the &lt;code&gt;bin&lt;/code&gt; key pointing to our executable file. For our package, we could use something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"bin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"create-mypackage-name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./index.js"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  A really basic package
&lt;/h3&gt;

&lt;p&gt;To start we need to initialize a project using the familiar &lt;code&gt;npm init&lt;/code&gt; command.&lt;br&gt;
This will create the basic scaffold for our package and we'll be able to set the requirements we saw in the previous step.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE&lt;br&gt;
If we want to create a scoped package now is the time to make it known to npm by adding our organization name before the package name.&lt;br&gt;
I.E.&lt;br&gt;
&lt;code&gt;@myorg/create-mypackage-name&lt;/code&gt; instead of &lt;code&gt;create-mypackage-name&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;NOTE&lt;br&gt;
When creating a scoped package NPM will default the package to private visibility. To publish the package as public we need to use &lt;code&gt;npm publish --access public&lt;/code&gt;.&lt;br&gt;
More on this topic can be found in the notes at the end of this article.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Once the init procedure is done, let's add a new file called &lt;code&gt;index.js&lt;/code&gt; (or &lt;code&gt;main.js&lt;/code&gt;, or whatever your default naming convention is).&lt;br&gt;
Then we meet the previous requirement: to define the &lt;code&gt;main&lt;/code&gt; and the &lt;code&gt;bin&lt;/code&gt; keys in &lt;code&gt;package.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Both keys need to be defined at the root level of your &lt;code&gt;package.json&lt;/code&gt;.&lt;br&gt;
Let's point &lt;code&gt;main&lt;/code&gt; to the file we just created:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"main"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./index.js"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we need to define the &lt;code&gt;bin&lt;/code&gt; property pointing to the main executable file of our package.&lt;br&gt;
The files defined here will be installed by npm into the PATH and be available to the package and the user.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;bin&lt;/code&gt; key is just a map of the command name to the local file name.&lt;/p&gt;

&lt;p&gt;As per the official documentation, if we have only a single executable, and its name should be the name of the package, we could just use a string as the value for &lt;code&gt;bin&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"bin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./index.js"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we want to be more verbose or we think we'll need to add more executables in the future, we can provide an object instead of a string, with a key named like our package (without the @org prefix).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"bin"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"create-mypackage-name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./index.js"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both these examples are equivalent in our context.&lt;/p&gt;

&lt;h4&gt;
  
  
  A simple &lt;code&gt;console.log&lt;/code&gt;
&lt;/h4&gt;

&lt;p&gt;In our &lt;code&gt;index.js&lt;/code&gt; add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cp"&gt;#!/usr/bin/env node
&lt;/span&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello World!&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;NOTE&lt;br&gt;
Please make sure that the file referenced in &lt;code&gt;bin&lt;/code&gt; starts with &lt;code&gt;#!/usr/bin/env node&lt;/code&gt;, otherwise the scripts won't be executed by node!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  Make the package available globally on your local machine
&lt;/h4&gt;

&lt;p&gt;We don't need to publish our package to test it.&lt;br&gt;
Executing the &lt;code&gt;npm link&lt;/code&gt; command inside the root of our project will make our local package available globally in our system.&lt;/p&gt;

&lt;p&gt;Next, we need to create a new directory in another path (i.e. &lt;code&gt;C:\test&lt;/code&gt;) and execute the command &lt;code&gt;npm link create-mypackage-name&lt;/code&gt; or &lt;code&gt;npm link @myorg/create-mypackage-name&lt;/code&gt; if you created a scoped package.&lt;br&gt;
Now our package will be available in the current directory. Yay!&lt;/p&gt;

&lt;p&gt;To be sure everything works as expected we need to type the following command in the terminal (from our test folder): &lt;code&gt;npx create-mypackage-name&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE&lt;br&gt;
&lt;code&gt;npx&lt;/code&gt; is not a typo, it's the command to run arbitrary commands from local or remote packages.&lt;br&gt;
&lt;a href="https://docs.npmjs.com/cli/v11/commands/npx" rel="noopener noreferrer"&gt;NPM Docs - npx&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The name of the command is the same we defined inside the &lt;code&gt;bin&lt;/code&gt; property in &lt;code&gt;package.json&lt;/code&gt;.&lt;br&gt;
If we can see the console.log in the terminal, everything is working properly!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE&lt;br&gt;
Now could be a great time to save our code in a repository on GitHub and publish our package.&lt;br&gt;
This way we can try to install it using the &lt;code&gt;npm create @myorg/mypackage-name@latest&lt;/code&gt; command and see if everything is ok.&lt;br&gt;
If we see the console.log message after running our command, we are on the right track!&lt;/p&gt;

&lt;p&gt;When creating a scoped package NPM will default the package visibility to private. To publish the package as public we need to use &lt;code&gt;npm publish --access public&lt;/code&gt;.&lt;br&gt;
More on this topic can be found in the following links.&lt;/p&gt;

&lt;p&gt;In this tutorial we won't cover how to publish a package, but the following links will surely help you:&lt;br&gt;
&lt;a href="https://docs.npmjs.com/creating-and-publishing-unscoped-public-packages" rel="noopener noreferrer"&gt;NPM Docs - Creating and publishing unscoped public packages&lt;/a&gt;&lt;br&gt;
&lt;a href="https://docs.npmjs.com/creating-and-publishing-unscoped-public-packages" rel="noopener noreferrer"&gt;NPM Docs - Creating and publishing scoped public packages&lt;/a&gt;&lt;br&gt;
&lt;a href="https://www.freecodecamp.org/news/how-to-create-and-publish-your-first-npm-package/" rel="noopener noreferrer"&gt;freeCodeCamp - How to Create and Publish an NPM Package – a Step-by-Step Guide&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  How to manage a more complex scaffolding
&lt;/h3&gt;

&lt;p&gt;Before we dive into the scaffolding package itself, it is important to understand how to edit the &lt;code&gt;package.json&lt;/code&gt; to better organize our code and files.&lt;/p&gt;

&lt;p&gt;Imagine we want to create a utility function in a file called &lt;code&gt;toUppercase.js&lt;/code&gt; inside the &lt;code&gt;utils&lt;/code&gt; folder.&lt;/p&gt;

&lt;p&gt;Scaffolding:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;index.js
package.json
utils
    toUppercase.js
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We want to use the &lt;code&gt;toUppercase.js&lt;/code&gt; module inside &lt;code&gt;index.js&lt;/code&gt;. To do so we need to import the file at the start of &lt;code&gt;index.js&lt;/code&gt; but this will not be sufficient and will throw a ERR_MODULE_NOT_FOUND error.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;If you published your package or you made it available globally on your local machine, go ahead and try.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To avoid this error we must update our &lt;code&gt;package.json&lt;/code&gt; to export all the files we need and change the import inside &lt;code&gt;index.js&lt;/code&gt; to be consistent with our package name.&lt;/p&gt;

&lt;p&gt;Inside &lt;code&gt;package.json&lt;/code&gt; let's add the &lt;code&gt;exports&lt;/code&gt; property:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"exports"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"."&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./index.js"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"./utils/*.js"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"./utils/*.js"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The official documentation states that: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The "exports" provides a modern alternative to "main" allowing multiple entry points to be defined, conditional entry resolution support between environments, and preventing any other entry points besides those defined in "exports".&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.npmjs.com/cli/v11/configuring-npm/package-json#exports" rel="noopener noreferrer"&gt;NPM Docs - exports&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This means we won't need the &lt;code&gt;main&lt;/code&gt; field anymore.&lt;br&gt;
In the &lt;code&gt;exports&lt;/code&gt; field we defined:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the default entry point &lt;code&gt;index.js&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;all other entry points inside the &lt;code&gt;utils&lt;/code&gt; folder&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In &lt;code&gt;index.js&lt;/code&gt; we update our import by self-referencing our package using its name.&lt;br&gt;
From:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;toUppercase&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;./utils/toUppercase.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;toUppercase&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@myorg/mypackage-name/utils/toUppercase.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is not a necessary step and only works if we define the &lt;code&gt;exports&lt;/code&gt; inside &lt;code&gt;package.json&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Since we defined the property in &lt;code&gt;exports&lt;/code&gt; with the &lt;code&gt;.js&lt;/code&gt; extension, we must remember to explicitly state the extension when importing our modules.&lt;/p&gt;

&lt;p&gt;This will throw an error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;toUppercase&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@myorg/mypackage-name/utils/toUppercase&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;-- NO EXTENSION&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will work:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;toUppercase&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@myorg/mypackage-name/utils/toUppercase.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;-- WITH EXTENSION&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;NOTE&lt;br&gt;
If we already published our package we need to update its patch value and publish it again.&lt;br&gt;
&lt;code&gt;npm version patch&lt;/code&gt; will update the version (i.e. from 0.0.1 to 0.0.2).&lt;br&gt;
&lt;code&gt;npm publish&lt;/code&gt; will publish the updated version of the package, so that we can install it using &lt;code&gt;npm create @myorg/mypackage-name@latest&lt;/code&gt; or &lt;code&gt;npm create @myorg/mypackage-name@0.0.2&lt;/code&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We can still test the package locally using the &lt;code&gt;npm link&lt;/code&gt; command as before.&lt;/p&gt;

&lt;h3&gt;
  
  
  A simple scaffolding package
&lt;/h3&gt;

&lt;p&gt;Now is the time to create our custom scaffolding package to bootstrap our projects!&lt;br&gt;
We need to take a couple of minutes to think about how we want your projects to be developed:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which framework do we want to use?

&lt;ul&gt;
&lt;li&gt;I.E. React? Vue? Astro?&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;What are the packages we use most often?

&lt;ul&gt;
&lt;li&gt;I.E. For Vue I find myself always installing Bootstrap, Sass, Vue Router, and Make JS Component&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;What are some common components or plugins that we always include in our project?

&lt;ul&gt;
&lt;li&gt;I.E. Header, Footer, Navigation, a simple state manager, some views...&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Create a new project
&lt;/h4&gt;

&lt;p&gt;When we have a clear idea of what we need the following step is to create this project step-by-step, as we did until today.&lt;br&gt;
We create everything we need and nothing more. We do not want to add specific details to this project.&lt;/p&gt;
&lt;h3&gt;
  
  
  A crossroad
&lt;/h3&gt;

&lt;p&gt;At this moment we are at a crossroads and in front of us have two ways to accomplish the same thing.&lt;/p&gt;

&lt;p&gt;One will allow us to have everything in a single package, easy to maintain but it'll need a bit more tweaks to really shine (&lt;em&gt;we won't cover these details right now&lt;/em&gt;).&lt;br&gt;
It needs a bit of knowledge of NodeJS and JS in order to be developed and maintained. Other than that it's still a nice way to pack everything up.&lt;/p&gt;

&lt;p&gt;The second way leverage NodeJS methods for executing commands, but requires us to create as many repositories as we need scaffolding variations.&lt;br&gt;
On the other hand, this makes updating the scaffolding really easy, and doesn't need to make changes and update the main package in order to have those updates available for us and our users.&lt;br&gt;
We need to execute one command using NodeJS &lt;code&gt;execSync&lt;/code&gt; but the whole process is faster and the starter kits are easy to maintain.&lt;/p&gt;

&lt;p&gt;Let's explore how every single method works.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE&lt;br&gt;
I will not, at this moment, focus on the meaning of single lines of code.&lt;br&gt;
I will probably make a new tutorial dedicated to some of the functions used in the following parts.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h3&gt;
  
  
  One package, many files
&lt;/h3&gt;

&lt;p&gt;First way, ready to go!&lt;/p&gt;

&lt;p&gt;Pros:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;single package to maintain&lt;/li&gt;
&lt;li&gt;with a bit of NodeJS and NPM knowledge it could really shine&lt;/li&gt;
&lt;li&gt;everything is in a single place&lt;/li&gt;
&lt;li&gt;Vite also does things this way&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;we need to copy/paste the files from a skeleton project&lt;/li&gt;
&lt;li&gt;if we don't want to copy/paste we need to better understand how git, NodeJS, and NPM work&lt;/li&gt;
&lt;li&gt;for every change in our scaffolding we need to publish a new version of the package&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  Update the scaffolding of the npm package
&lt;/h4&gt;

&lt;p&gt;Back to our package!&lt;br&gt;
We want to create a &lt;code&gt;template&lt;/code&gt; directory, and if we want to be future proof we should also make a specific framework/library/tech directory.&lt;br&gt;
In this example, we will create a &lt;code&gt;vue&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;This is the current scaffolding of our npm package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;index.js
package.json
utils
    toUppercase.js
template
    vue
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Inside the &lt;code&gt;vue&lt;/code&gt; folder we will copy everything from the project we created in the previous step.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE&lt;br&gt;
Of course we will not copy the &lt;code&gt;node_modules&lt;/code&gt; folder and neither the &lt;code&gt;package-lock.json&lt;/code&gt; file.&lt;br&gt;
A basic skeleton of a fresh new project will be enough.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h4&gt;
  
  
  How to interact with the user and copy the scaffolding files
&lt;/h4&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE&lt;br&gt;
As mentioned before this part will be more of a copy/paste for now. If you are interested I will make a future article focusing on some of the methods and packages I used.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We need to ask our users about the project our package will create.&lt;br&gt;
To accomplish this task we need the &lt;a href="https://www.npmjs.com/package/inquirer" rel="noopener noreferrer"&gt;inquirer&lt;/a&gt; package (the following code is referencing the linked version, but feel free to use the new version of inquirer and edit the code example).&lt;/p&gt;

&lt;p&gt;After installing inquirer we need to update our main entry point, &lt;code&gt;index.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cp"&gt;#!/usr/bin/env node
&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;toUppercase&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@myorg/mypackage-name/utils/toUppercase.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;inquirer&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;inquirer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;inquirer&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;input&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;projectName&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Enter your project name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;obi-wan-kenobi&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;toUppercase&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;projectName&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isTtyError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="c1"&gt;// Prompt couldn't be rendered in the current environment&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cannot render the prompt...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}))();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Running our project (locally or after publishing a new version and installing it again) will give us a nice prompt inside our terminal, asking for the name of our shiny new project.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flxprvfdzpgnwln7mh5gi.PNG" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flxprvfdzpgnwln7mh5gi.PNG" alt=" " width="762" height="216"&gt;&lt;/a&gt;&lt;br&gt;
Perfection!&lt;/p&gt;

&lt;p&gt;Instead of printing the project name all in uppercase inside the console, we will copy the files and folders from &lt;code&gt;template/vue&lt;/code&gt; inside the current project directory.&lt;/p&gt;

&lt;p&gt;We must create a new file inside the &lt;code&gt;utils&lt;/code&gt; folder: &lt;code&gt;createProject.js&lt;/code&gt;.&lt;br&gt;
Inside this file we will add two functions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a &lt;code&gt;init&lt;/code&gt; function that will start the whole process&lt;/li&gt;
&lt;li&gt;a &lt;code&gt;copyTemplateFilesAndFolders&lt;/code&gt; function that will recursively copy all the files and folders from the template directory
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs/promises&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;fileURLToPath&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:url&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;chalk&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chalk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;copyTemplateFilesAndFolders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;projectName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;filesAndFolders&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;filesAndFolders&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentSource&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentDestination&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lstat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentSource&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isDirectory&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mkdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentDestination&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;copyTemplateFilesAndFolders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentSource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currentDestination&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

            &lt;span class="c1"&gt;// If the file is package.json we replace the default name with the one provided by the user&lt;/span&gt;
            &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/package.json/&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentSource&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentPackageJson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentSource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
                &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newFileContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;currentPackageJson&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/custom-scaffolding/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;projectName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

                &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentDestination&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newFileContent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;copyFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentSource&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;currentDestination&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;init&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;projectName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;destination&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nx"&gt;projectName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fileURLToPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../template/vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;📑  Copying files...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mkdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;copyTemplateFilesAndFolders&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;source&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;projectName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;📑  Files copied...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chalk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;green&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`\ncd &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;projectName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\nnpm install\nnpm run dev`&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;To make the message more pretty in the terminal we could install &lt;a href="https://www.npmjs.com/package/chalk" rel="noopener noreferrer"&gt;chalk&lt;/a&gt;.&lt;br&gt;
This is not a mandatory step but a nice one. Of course, if we don't want to use this library it's sufficient to remove all references to it from the previous code.&lt;/p&gt;

&lt;p&gt;Just a bit of context before we continue.&lt;br&gt;
The previous code has two functions. The &lt;code&gt;init&lt;/code&gt; function receives the project name and with the help of the &lt;code&gt;path&lt;/code&gt; module we create a path (of course) pointing to a folder named like the project name we provided, concatenated to our current working folder (this comes from &lt;code&gt;process.cwd()&lt;/code&gt;).&lt;br&gt;
The &lt;code&gt;join&lt;/code&gt; methods will use the correct path separator based on the OS the package is installed on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;destination&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nx"&gt;projectName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the help of the &lt;code&gt;fs&lt;/code&gt; module NodeJS can use the method &lt;code&gt;mkdir&lt;/code&gt; to create a new folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mkdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to resolve the path to our scaffolding files and folders. To do this we will use the &lt;code&gt;resolve&lt;/code&gt; method of the &lt;code&gt;path&lt;/code&gt; module:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;source&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;resolve&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;dirname&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;fileURLToPath&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;import&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;meta&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;url&lt;/span&gt;&lt;span class="p"&gt;)),&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;../template/vue&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;I leave to the official documentation and to your curiosity the explanation for this bit ;)&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;code&gt;copyTemplateFilesAndFolders&lt;/code&gt; will be called with three arguments: &lt;code&gt;source&lt;/code&gt; (where the template is), &lt;code&gt;destination&lt;/code&gt; (the folder just created and named after what we typed in the prompt), &lt;code&gt;projectName&lt;/code&gt; (the name of our project).&lt;/p&gt;

&lt;p&gt;&lt;code&gt;copyTemplateFilesAndFolders&lt;/code&gt; will then copy every single folder and file from the &lt;code&gt;source&lt;/code&gt; to the &lt;code&gt;destination&lt;/code&gt;. For each folder it will recursively call itself to copy every file from it.&lt;/p&gt;

&lt;p&gt;When the function finds the &lt;code&gt;package.json&lt;/code&gt; file it will overwrite the default project name with the one we provided.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE&lt;br&gt;
We could also parse the file content as JSON and overwrite the name property using direct access.&lt;br&gt;
We will then re-encode the object as JSON string and write it back to the file.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now it's a good time to test again our package and see if everything works correctly.&lt;br&gt;
If the test with the local package is showing you &lt;code&gt;index.js&lt;/code&gt; instead of executing it, just unlink and re-link the project.&lt;/p&gt;

&lt;p&gt;With this step, we are done! Now we can create a new project with everything we want, using a single npm command.&lt;/p&gt;
&lt;h3&gt;
  
  
  One package, many repos
&lt;/h3&gt;

&lt;p&gt;This is the last method to tackle this problem.&lt;/p&gt;

&lt;p&gt;Pros:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;it's easier to add a new scaffolding and to keep things up to date&lt;/li&gt;
&lt;li&gt;only one single package to update and publish&lt;/li&gt;
&lt;li&gt;starter kit repos are easy to maintain&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Cons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;you don't really need a npm package to install a git repo, so it's a bit of an extra step&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;
  
  
  A new old repo
&lt;/h4&gt;

&lt;p&gt;First things first!&lt;br&gt;
Remember the template repository we saw at the start of this tutorial? We are going back to it and will sprinkle a bit of NodeJS and NPM magic dust over it.&lt;/p&gt;
&lt;h4&gt;
  
  
  How to interact with the user and install the starter kit
&lt;/h4&gt;

&lt;p&gt;As we did for the other version, we need to use &lt;a href="https://www.npmjs.com/package/inquirer" rel="noopener noreferrer"&gt;inquirer&lt;/a&gt; to ask our users (or our future selves) the name of the project and what kit we want to use.&lt;/p&gt;

&lt;p&gt;Since we want to be able to define more than one starter kit and we want things to be tidy and clean, we should create a new file inside the &lt;code&gt;utils&lt;/code&gt; folder called &lt;code&gt;allowedPackages.js&lt;/code&gt;.&lt;br&gt;
This package will define the scope (our GitHub username -- &lt;code&gt;my-github-username&lt;/code&gt;), the starter kit (an array of strings), and a method that will create an array of allowed packages (this will come in handy later for security purposes).&lt;/p&gt;

&lt;p&gt;Here's the content of the file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;scope&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;my-github-username&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;starterKits&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;vue&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;allowedPackages&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;starterKits&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;kit&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;kit&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-starter-kit`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We need to update &lt;code&gt;index.js&lt;/code&gt; to import this file and to ask our users which kit they want to install.&lt;br&gt;
Here's the updated &lt;code&gt;index.js&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="cp"&gt;#!/usr/bin/env node
&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;init&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@myorg/mypackage-name/utils/createProject.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;allowedPackages&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;starterKits&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;scope&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@myorg/mypackage-name/utils/allowedPackages.js&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;inquirer&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;inquirer&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;inquirer&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;prompt&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;input&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;projectName&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Enter your project name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;default&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;obi-wan-kenobi&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;list&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;prefix&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Select a starter kit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;choices&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;starterKits&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;requestedPackage&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;scope&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;prefix&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;-starter-kit`&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nf"&gt;allowedPackages&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;requestedPackage&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Invalid package&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; 
&lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="err"&gt; &lt;/span&gt; &lt;span class="nf"&gt;init&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;answers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;projectName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;requestedPackage&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isTtyError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c1"&gt;// Prompt couldn't be rendered in the current environment&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cannot render the prompt...&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}))();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We added a new option to our users: what starter kit they want.&lt;br&gt;
Note that we check if the selected package is valid. If not it means the user tried to send some arbitrary value and the script will throw an error and stop the execution.&lt;/p&gt;

&lt;p&gt;Of course, the &lt;code&gt;createProject.js&lt;/code&gt; module changed as well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;fs/promises&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;node:path&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;chalk&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;chalk&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;execSync&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;node:child_process&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;updatePackageJson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;projectPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;requestedPackage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;projectName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chalk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Updating package.json...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;packagePath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;projectPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;package.json&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lstat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;packagePath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isFile&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentPackageJson&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;readFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;packagePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;newFileContent&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;currentPackageJson&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;requestedPackage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;projectName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;writeFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;packagePath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newFileContent&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;utf8&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;removeGitFolder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;projectPath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chalk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Removing .git folder...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;gitFolderPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;projectPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;.git&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;stat&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lstat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gitFolderPath&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;stat&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;isDirectory&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;rm&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;gitFolderPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;recursive&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;init&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;projectName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;requestedPackage&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;currentDir&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;destination&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;currentDir&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;projectName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;fullURL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;`https://github.com/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;requestedPackage&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.git`&lt;/span&gt;

        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chalk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;📑  Copying files...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;fs&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;mkdir&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="nf"&gt;execSync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`git clone --depth 1 &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;fullURL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; .`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;stdio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;inherit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;destination&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;

        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chalk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;gray&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;📑  Files copied...&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;removeGitFolder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;updatePackageJson&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;destination&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;requestedPackage&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;projectName&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chalk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;green&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`\ncd &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;projectName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;\nnpm install\nnpm run dev`&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;chalk&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;red&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On this one, we have simplified a couple of things.&lt;br&gt;
The &lt;code&gt;copyTemplateFilesAndFolders&lt;/code&gt; doesn't exist anymore. This time we need two functions to update the default &lt;code&gt;package.json&lt;/code&gt; we are getting from the starter kit repo and a function to remove the &lt;code&gt;.git&lt;/code&gt; folder from the cloned repo.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;init&lt;/code&gt; function will use &lt;code&gt;execSync&lt;/code&gt; to execute the git clone command for our starter kit repo:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git clone &lt;span class="nt"&gt;--depth&lt;/span&gt; 1 &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;fullURL&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt; &lt;span class="nb"&gt;.&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will clone the repo in the project folder defined by the &lt;code&gt;cwd&lt;/code&gt; property in the second parameter of the &lt;code&gt;execSync&lt;/code&gt; command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nl"&gt;stdio&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;inherit&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;cwd&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;destination&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;NOTE&lt;br&gt;
The &lt;code&gt;exec&lt;/code&gt; and &lt;code&gt;execSync&lt;/code&gt; methods of NodeJS use a shell to execute our command. Since we are also adding some user-provided data we need to be careful not to allow arbitrary commands to be executed (i.e. &lt;code&gt;rm -rf&lt;/code&gt;). This is the reason for our previous validation inside &lt;code&gt;index.js&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;If the user sends an invalid selection (i.e. not a valid starter kit, some arbitrary commands, etc...), our code will not allow that string to be passed to &lt;code&gt;execSync&lt;/code&gt; and be executed. We will stop everything and be safe.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As before we update the &lt;code&gt;package.json&lt;/code&gt; file so the name of the project will be the same one the user provided.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I decided to make this tutorial for a reason: to show how we can make things following the example set by others (Vite in this specific case) and how we can add some of our needs on top of that.&lt;/p&gt;

&lt;p&gt;This tutorial doesn't want to be a comprehensive explanation of how to create this kind of package. As I said before is more like a finger pointing in a direction. If you want, follow that direction, make your own mistakes along the way, and learn.&lt;/p&gt;

&lt;p&gt;At the end of that path, you will find knowledge and maybe you'll have your own personal scaffolder!&lt;/p&gt;

&lt;p&gt;If this article was helpful or want to start a conversation, feel free to reach out in the comments or on &lt;a href="https://www.linkedin.com/in/donato-riccio-wda/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;br&gt;&lt;br&gt;
I'll be happy to receive any feedback or ideas for future articles and tutorials.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.npmjs.com/" rel="noopener noreferrer"&gt;NPM Docs&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.npmjs.com/cli/v11/commands/npm-init" rel="noopener noreferrer"&gt;npm init - (aliases: create, innit)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.npmjs.com/cli/v11/configuring-npm/package-json" rel="noopener noreferrer"&gt;Configure package.json&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.npmjs.com/creating-and-publishing-unscoped-public-packages" rel="noopener noreferrer"&gt;NPM Docs - Creating and publishing unscoped public packages&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.npmjs.com/creating-and-publishing-unscoped-public-packages" rel="noopener noreferrer"&gt;NPM Docs - Creating and publishing scoped public packages&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;a href="https://nodejs.org/docs/latest/api/" rel="noopener noreferrer"&gt;NodeJS Docs&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nodejs.org/api/child_process.html" rel="noopener noreferrer"&gt;Child Process - (execSync)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nodejs.org/docs/latest/api/fs.html#file-system" rel="noopener noreferrer"&gt;File System - (fs)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;

&lt;a href="https://git-scm.com/doc" rel="noopener noreferrer"&gt;Git Docs&lt;/a&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://git-scm.com/docs/git-clone#Documentation/git-clone.txt-code--depthltdepthgtcode" rel="noopener noreferrer"&gt;clone - (--depth 1)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;&lt;a href="https://www.freecodecamp.org/news/how-to-create-and-publish-your-first-npm-package/" rel="noopener noreferrer"&gt;freeCodeCamp - How to Create and Publish an NPM Package – a Step-by-Step Guide&lt;/a&gt;&lt;/li&gt;

&lt;li&gt;&lt;a href="https://github.com/DonnieRich/templar" rel="noopener noreferrer"&gt;GitHub Reference Repo&lt;/a&gt;&lt;/li&gt;

&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>javascript</category>
      <category>npm</category>
      <category>vite</category>
    </item>
    <item>
      <title>API key management on Netlify</title>
      <dc:creator>Donato Riccio</dc:creator>
      <pubDate>Sat, 08 Jul 2023 13:20:44 +0000</pubDate>
      <link>https://dev.to/donnierich/api-key-management-on-netlify-4il9</link>
      <guid>https://dev.to/donnierich/api-key-management-on-netlify-4il9</guid>
      <description>&lt;p&gt;This is a tutorial aimed to help junior devs correctly manage their API keys (or other secrets) when publishing a website on the Netlify platform.&lt;/p&gt;

&lt;h2&gt;
  
  
  Pre-requisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Basic knowledge of HTML, CSS, JavaScript&lt;/li&gt;
&lt;li&gt;Basic knowledge of Vite, VueJS, and Axios&lt;/li&gt;
&lt;li&gt;Basic knowledge of VisualStudio Code&lt;/li&gt;
&lt;li&gt;Just a bit of experience with the CLI&lt;/li&gt;
&lt;li&gt;A GitHub repository&lt;/li&gt;
&lt;li&gt;How to deploy a website on Netlify&lt;/li&gt;
&lt;li&gt;A website/project/web app already deployed on Netlify&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What you will learn (table of contents)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;How to install and use the Netlify CLI&lt;/li&gt;
&lt;li&gt;How to set and use environment variables&lt;/li&gt;
&lt;li&gt;How to write serverless functions&lt;/li&gt;
&lt;li&gt;How to use serverless functions to communicate with the APIs&lt;/li&gt;
&lt;li&gt;Conclusion&lt;/li&gt;
&lt;li&gt;Resources&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to install and use the Netlify CLI
&lt;/h2&gt;

&lt;p&gt;This is one of the easiest steps of the entire tutorial.&lt;br&gt;
From the Netlify documentation about the CLI (you can find it &lt;a href="https://docs.netlify.com/cli/get-started/" rel="noopener noreferrer"&gt;here&lt;/a&gt;) this is all you need to install the Netlify CLI. Yay! :)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;npm &lt;span class="nb"&gt;install &lt;/span&gt;netlify-cli &lt;span class="nt"&gt;-g&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now you can use the &lt;code&gt;netlify&lt;/code&gt; command to manage your local website. You can also use the alias &lt;code&gt;ntl&lt;/code&gt; to save some time :)&lt;/p&gt;

&lt;h3&gt;
  
  
  Login to Netlify
&lt;/h3&gt;

&lt;p&gt;Now you need to authorize Netlify CLI by obtaining an access token. Just type the following command and authorize the application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ntl login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Link your local environment to Netlify
&lt;/h3&gt;

&lt;p&gt;If you have already deployed your website on Netlify, now you just have to &lt;em&gt;link&lt;/em&gt; both environments together.&lt;br&gt;
You can do this using this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ntl &lt;span class="nb"&gt;link&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Run your build
&lt;/h3&gt;

&lt;p&gt;With the following command, you can run your local build using the Netlify CLI to simulate the behavior of running the build on Netlify:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ntl dev
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to set and use environment variables
&lt;/h2&gt;

&lt;p&gt;If you are not familiar with the concept of .env file and environment variables you can refer to this over-simplified definition just to understand the basics:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An .env file is just a plain text file containing key/value pairs of variables.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;env&lt;/em&gt; is short for &lt;em&gt;environment&lt;/em&gt;, because the values defined here are the variables available for all our environment.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Set environment variables
&lt;/h3&gt;

&lt;p&gt;You can set these variables by just writing them down inside your .env file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;MY_KEY=value
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: always remember to add your .env file to .gitignore or all the variables will be visible inside your repository!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Netlify UI makes the process to write and manage environment variables really easy. Just go to your site &lt;em&gt;Control Panel&lt;/em&gt; &amp;gt; &lt;em&gt;Site settings&lt;/em&gt; &amp;gt; &lt;em&gt;Environment variables&lt;/em&gt;.&lt;br&gt;
Write the key and the value, leaving the variable available for all the scopes (in this tutorial I will not cover the variable scopes).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;: make sure to have the &lt;em&gt;Sensitive variable policy&lt;/em&gt; set up on &lt;em&gt;Require approval&lt;/em&gt; for untrusted deploys!&lt;br&gt;
More on that &lt;a href="https://docs.netlify.com/environment-variables/get-started/#sensitive-variable-policy" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you linked your local development environment to your Netlify site, you already have the environment variables available without the need to write the .env file!&lt;/p&gt;

&lt;p&gt;You can verify this by executing the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ntl &lt;span class="nb"&gt;env&lt;/span&gt;:list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Use environment variables
&lt;/h3&gt;

&lt;p&gt;To use the environment variables this is all you need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SECRET_API_KEY&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;process.env&lt;/code&gt; gets all the environment variables and with a simple &lt;em&gt;destructuring&lt;/em&gt; you can get the keys you want.&lt;/p&gt;

&lt;p&gt;That's all for the environment variables!&lt;br&gt;
Don't worry! In the next steps, I'll show you where to place this line of code :)&lt;/p&gt;
&lt;h2&gt;
  
  
  How to write serverless functions
&lt;/h2&gt;

&lt;p&gt;A serverless function on Netlify is just a JS function that returns a promise. As per the Netlify documentation:&lt;br&gt;
&lt;em&gt;To create a synchronous function, use the following general syntax in your JavaScript function file to export a handler method&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// your server-side functionality&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also use the ES Module syntax:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// your server-side functionality&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;&lt;br&gt;
Netlify provides the event and context parameters when the function is invoked.&lt;br&gt;
More on that &lt;a href="https://docs.netlify.com/functions/create/?fn-language=js#synchronous-function-format-2" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Where to place serverless functions
&lt;/h3&gt;

&lt;p&gt;The default path used by Netlify for serverless functions is &lt;code&gt;YOUR_BASE_DIRECTORY/netlify/functions&lt;/code&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;&lt;br&gt;
The function’s endpoint name is &lt;em&gt;case-sensitive&lt;/em&gt; and determined by its filename or the name of its dedicated parent directory.&lt;/p&gt;

&lt;p&gt;I.E. If you want an endpoint with the name &lt;code&gt;hello&lt;/code&gt; you should save your function in one of the following ways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;netlify/functions/hello.js&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;netlify/functions/hello/hello.js&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;netlify/functions/hello/index.js&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because the endpoint name is &lt;em&gt;case-sensitive&lt;/em&gt; if you name your function &lt;code&gt;myFunction&lt;/code&gt;, your endpoint will look like this: &lt;code&gt;netlify/functions/myFunction.js&lt;/code&gt;.&lt;br&gt;
For the same reason if you name your function &lt;code&gt;my-function&lt;/code&gt;, your endpoint will be: &lt;code&gt;netlify/functions/my-function.js&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;
  
  
  What to write inside the function
&lt;/h3&gt;

&lt;p&gt;The easiest thing to do is to just make the function return a "Hello World!"&lt;br&gt;
Using the basic example from the &lt;a href="https://docs.netlify.com/functions/create/?fn-language=js#synchronous-function-format-2" rel="noopener noreferrer"&gt;Netlify documentation&lt;/a&gt; the &lt;code&gt;hello.js&lt;/code&gt; function will look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// your server-side functionality&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello World&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will return an object with a &lt;code&gt;statusCode&lt;/code&gt; and a &lt;code&gt;body&lt;/code&gt; properties. The &lt;code&gt;statusCode&lt;/code&gt; with value &lt;code&gt;200&lt;/code&gt; means the request was successful.&lt;br&gt;
The &lt;code&gt;body&lt;/code&gt; will contain a &lt;code&gt;JSON&lt;/code&gt; formatted string representing the object we want to get from the function. In this example is just an object with a &lt;code&gt;message&lt;/code&gt; property.&lt;/p&gt;

&lt;p&gt;Let's proceed to the next step!&lt;/p&gt;
&lt;h2&gt;
  
  
  How to use serverless functions to communicate with the APIs
&lt;/h2&gt;

&lt;p&gt;Time to use your function!&lt;br&gt;
After a successful test call, you will add the code needed to call the API endpoint you want.&lt;/p&gt;
&lt;h3&gt;
  
  
  Call the function
&lt;/h3&gt;

&lt;p&gt;The following code examples are taken from a VueJS project, using &lt;code&gt;axios&lt;/code&gt; to call both the serverless functions and the APIs.&lt;/p&gt;

&lt;p&gt;To call &lt;code&gt;hello.js&lt;/code&gt; from &lt;code&gt;App.vue&lt;/code&gt; the code is as simple as this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/.netlify/functions/hello&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// handle success&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;helloResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// handle error&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you are a bit familiar with VueJS you'll know this code can be placed inside a function defined in the &lt;code&gt;methods&lt;/code&gt; property or inside the &lt;code&gt;mounted&lt;/code&gt; method.&lt;br&gt;
&lt;code&gt;helloResult&lt;/code&gt; is just a property of &lt;code&gt;data&lt;/code&gt; and is used to memorize the value returned from the &lt;code&gt;hello.js&lt;/code&gt; function.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;&lt;br&gt;
To get the "Hello World!" text you need to access the &lt;code&gt;message&lt;/code&gt; property inside &lt;code&gt;response.data&lt;/code&gt;.&lt;br&gt;
The &lt;code&gt;message&lt;/code&gt; property is the same property you defined in the previous step&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Make sure to test your code in the browser (remember to run &lt;code&gt;ntl dev&lt;/code&gt; or &lt;code&gt;netlify dev&lt;/code&gt; in the terminal to get both the Netlify local environment and your project up and running as you did in the Run your build step)&lt;/p&gt;

&lt;p&gt;If everything works on your local machine, is time to push to your repository and test again everything on your live website!&lt;/p&gt;
&lt;h3&gt;
  
  
  Read environment variables from the serverless function
&lt;/h3&gt;

&lt;p&gt;You just tested the simplest function you could write and everything went smoothly! To make a secure call to the API you want you'll first need to &lt;em&gt;read&lt;/em&gt; the &lt;em&gt;API key&lt;/em&gt; from your &lt;em&gt;environment variables&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Do you remember this step? This is where you find out where to place that line of code!&lt;/p&gt;

&lt;p&gt;Go to the Set environment variables step and create a new variable called &lt;code&gt;SECRET_API_KEY&lt;/code&gt; (spoiler: it will not be secret!) with the value you want.&lt;/p&gt;

&lt;p&gt;On your local machine run the command to get the list of all environment variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ntl &lt;span class="nb"&gt;env&lt;/span&gt;:list
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you can see the &lt;code&gt;SECRET_API_KEY&lt;/code&gt; entry, you did everything right!&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;&lt;br&gt;
You can also check the variables values by typing &lt;code&gt;y&lt;/code&gt; when the terminal ask you: &lt;strong&gt;Show values?(y/N)&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now is the time to create a new function called &lt;code&gt;almost-secret.js&lt;/code&gt; that'll give you the value of the &lt;code&gt;SECRET_API_KEY&lt;/code&gt; env variable.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;almost-secret.js&lt;/code&gt; code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// your server-side functionality&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;SECRET_API_KEY&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;SECRET_API_KEY&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Calling this function will give you the value of your &lt;code&gt;SECRET_API_KEY&lt;/code&gt; variable... but, wait... why should you bring on your front-end such information?&lt;/p&gt;

&lt;p&gt;You shouldn't! This is just an example to show how to read and use your env variables from a serverless function.&lt;br&gt;
In the next example, you will see how to properly use a serverless function to call an API without exposing your API key.&lt;/p&gt;

&lt;p&gt;Before that, let's push everything on the repository and check it on the live site.&lt;/p&gt;
&lt;h3&gt;
  
  
  Call QuizAPI passing the API key securely
&lt;/h3&gt;

&lt;p&gt;In this last example, you will learn how to put it all together and make secure calls to every API you need.&lt;br&gt;
The API used is from &lt;a href="https://quizapi.io/docs/1.0/overview" rel="noopener noreferrer"&gt;QuizAPI&lt;/a&gt;. In their documentation, they suggest attaching the API key to a request as an &lt;code&gt;HTTP header&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;X-Api-Key: YOUR_API_KEY
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Register to &lt;a href="https://quizapi.io/register" rel="noopener noreferrer"&gt;QuizAPI&lt;/a&gt; and get your API key, then add that key to a new env variable on Netlify (es. &lt;code&gt;QUIZ_API_TOKEN&lt;/code&gt;).&lt;br&gt;
The last thing to do is to create a new function called &lt;code&gt;quizapi.js&lt;/code&gt;. This function will call the &lt;code&gt;questions&lt;/code&gt; endpoint (more on that &lt;a href="https://quizapi.io/docs/1.0/endpoints#%D0%B5ndpoints" rel="noopener noreferrer"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;To make an HTTP call from a serverless function you need to import &lt;code&gt;axios&lt;/code&gt; (you already installed the dependency in the previous steps).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;NOTE&lt;/strong&gt;&lt;br&gt;
I will not cover how to use &lt;code&gt;axios&lt;/code&gt; and how to add headers to a request since it's a pre-requisite for following this tutorial&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let's take a look at the &lt;code&gt;quizapi.js&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="c1"&gt;// your server-side functionality&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;QUIZ_API_TOKEN&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
            &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;X-Api-Key&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;QUIZ_API_TOKEN&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://quizapi.io/api/v1/questions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="c1"&gt;// handle success&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
        &lt;span class="p"&gt;};&lt;/span&gt;

    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="c1"&gt;// Could be a custom message or object i.e. JSON.stringify(err)&lt;/span&gt;
            &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;handler&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's a little more complex than the other two, is it?&lt;br&gt;
Don't worry, I will explain this function almost line by line.&lt;/p&gt;

&lt;p&gt;The first line just imports &lt;code&gt;axios&lt;/code&gt; inside the function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;axios&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After the common code for all the Netlify serverless functions, you can spot the line taking care of retrieving the &lt;code&gt;QUIZ_API_TOKEN&lt;/code&gt; env variable value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;QUIZ_API_TOKEN&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After that, there is the code used to add parameters and header to the &lt;code&gt;axios&lt;/code&gt; request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;X-Api-Key&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;QUIZ_API_TOKEN&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;limit&lt;/code&gt; property is a parameter taken from the &lt;a href="https://quizapi.io/docs/1.0/limit" rel="noopener noreferrer"&gt;QuizAPI documentation&lt;/a&gt;&lt;br&gt;
The &lt;code&gt;X-Api-Key&lt;/code&gt; property is where to place the value of &lt;code&gt;QUIZ_API_TOKEN&lt;/code&gt; as explained by the &lt;a href="https://quizapi.io/docs/1.0/authentication" rel="noopener noreferrer"&gt;QuizAPI documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The function will now make the call to the API, passing along parameters and headers:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://quizapi.io/api/v1/questions&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the API responds with an error, the function will throw an exception (this is why everything is wrapped inside a &lt;code&gt;try/catch&lt;/code&gt; block):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;errors&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If there are no errors, the function will return an object already familiar to you:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the response property, we add the value of &lt;code&gt;response.data&lt;/code&gt; since the endpoint returns an array of strings that &lt;code&gt;axios&lt;/code&gt; put right inside the &lt;code&gt;data&lt;/code&gt; property (if you are familiar with &lt;code&gt;axios&lt;/code&gt; you already know how to check this).&lt;/p&gt;

&lt;p&gt;In case of errors the function will go to the &lt;code&gt;catch&lt;/code&gt; block and return an object with a &lt;code&gt;statusCode&lt;/code&gt; of 500 (generic server error) and the error message:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;statusCode&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="c1"&gt;// Could be a custom message or object i.e. JSON.stringify(err)&lt;/span&gt;
        &lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;response&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To call this function from &lt;code&gt;App.vue&lt;/code&gt; (or any other component) the code is almost the same as the one used before:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;axios&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/.netlify/functions/quizapi&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;then&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// handle success&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;quizApiQuestion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;question&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;catch&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// handle error&lt;/span&gt;
        &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Test the call on your local machine
&lt;/h3&gt;

&lt;p&gt;If you didn't stop the local environment, go to your browser and check if you can get a question from the QuizAPI endpoint!&lt;br&gt;
After that go further and push everything on your repo to also test the call from the live site.&lt;/p&gt;
&lt;h3&gt;
  
  
  Test the call on the live site
&lt;/h3&gt;

&lt;p&gt;If you can get a question from QuizAPI from your live website, great!&lt;/p&gt;

&lt;p&gt;If not, maybe you are facing this kind of error: &lt;code&gt;'Error: Cannot find module '/var/task/node_modules/axios/dist/node/axios.cjs'&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;To solve this error create a file called &lt;code&gt;netlify.toml&lt;/code&gt; and add this code inside it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[functions]&lt;/span&gt;
  &lt;span class="py"&gt;node_bundler&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"esbuild"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Commit, push, and test again!&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;When calling external API services from your front-end project always remember to keep hidden and secured your API keys (or other sensitive pieces of information).&lt;br&gt;
One way to do this is to leverage the power of Netlify serverless functions that can act as API endpoints, read environment variables, and make calls to other APIs.&lt;/p&gt;

&lt;p&gt;If this article was helpful or want to start a conversation, feel free to reach out in the comments or on &lt;a href="https://www.linkedin.com/in/donato-riccio-wda/" rel="noopener noreferrer"&gt;LinkedIn&lt;/a&gt;&lt;br&gt;
I'll be happy to receive any feedback or ideas for future articles and tutorials.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.netlify.com/cli/get-started/" rel="noopener noreferrer"&gt;Netlify CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.netlify.com/environment-variables/get-started/" rel="noopener noreferrer"&gt;Netlify Environment Variables&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.netlify.com/functions/create/?fn-language=js" rel="noopener noreferrer"&gt;Netlify Serverless Functions&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://youtu.be/PCDhpRms4Ek" rel="noopener noreferrer"&gt;Up and running with serverless functions - YouTube Playlist&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://quizapi.io/docs/1.0/overview" rel="noopener noreferrer"&gt;QuizAPI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://answers.netlify.com/t/error-with-scheduled-functions-and-axios-error-cannot-find-module-var-task-node-modules-axios-dist-node-axios-cjs/94186" rel="noopener noreferrer"&gt;Cannot find module error - Netlify Answers&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/DonnieRich/api-key-management" rel="noopener noreferrer"&gt;GitHub Example Repo&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>beginners</category>
      <category>javascript</category>
      <category>netlify</category>
    </item>
    <item>
      <title>Laravel’s ForwardsCalls trait</title>
      <dc:creator>Donato Riccio</dc:creator>
      <pubDate>Wed, 21 Jun 2023 14:01:23 +0000</pubDate>
      <link>https://dev.to/donnierich/laravels-forwardscalls-trait-493i</link>
      <guid>https://dev.to/donnierich/laravels-forwardscalls-trait-493i</guid>
      <description>&lt;p&gt;In &lt;a href="https://dev.to/giuliano1993/the-power-of-magic-methods-and-late-static-binding-4bj3"&gt;the previous article&lt;/a&gt;, &lt;a href="https://dev.to/giuliano1993"&gt;Giuliano&lt;/a&gt; showed us how to leverage PHP’s Magic Methods and Late Biding to create a powerful architecture.&lt;/p&gt;

&lt;p&gt;This, however, is neither a secret nor a new cutting-edge OOP pattern.&lt;/p&gt;

&lt;p&gt;This same system has been used in Laravel since version 4.0* albeit in the more PHP plain way, using &lt;code&gt;call_user_func_array&lt;/code&gt; (&lt;a href="https://github.com/laravel/framework/blob/4.0/src/Illuminate/Database/Eloquent/Model.php" rel="noopener noreferrer"&gt;Laravel Model Class&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ForwardsCalls&lt;/code&gt; trait has been present since version 5.7 and if you read the first part of this series you are already familiar with the concept of using this method to simplify your development. Pretty cool, right?&lt;/p&gt;

&lt;p&gt;The devs working on the Laravel Framework thought the exact same thing (I suppose), and created the &lt;code&gt;ForwardsCalls&lt;/code&gt; trait.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE&lt;br&gt;
In this article we will reference Laravel 9.x, but the principles should be valid for all the versions that implement the &lt;code&gt;ForwardsCalls&lt;/code&gt; trait. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Table of contents
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Everyone's using it!&lt;/li&gt;
&lt;li&gt;The Model Class&lt;/li&gt;
&lt;li&gt;
The ForwardsCalls trait

&lt;ul&gt;
&lt;li&gt;Digging deeper&lt;/li&gt;
&lt;li&gt;Pre-requisite: ExportData - part one&lt;/li&gt;
&lt;li&gt;The Exporter Logic&lt;/li&gt;
&lt;li&gt;ExportManager&lt;/li&gt;
&lt;li&gt;IExporter, CsvExporter, XmlExporter&lt;/li&gt;
&lt;li&gt;ExportData - part two&lt;/li&gt;
&lt;li&gt;Run the command&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;In conclusion&lt;/li&gt;

&lt;/ul&gt;

&lt;h2&gt;
  
  
  Everyone's using it!
&lt;/h2&gt;

&lt;p&gt;One of the first instances where every developer using Laravel takes advantage of this approach is when they query their database through a &lt;code&gt;Model&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Look at this line of code extracted from a class called &lt;code&gt;ProjectController&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nv"&gt;$projects&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Project&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;orderByDesc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Pretty ordinary, right?&lt;/p&gt;

&lt;p&gt;If you would dive deeper in the &lt;code&gt;orderByDesc&lt;/code&gt; method, where would you go looking?&lt;br&gt;
Probably inside the &lt;code&gt;Project&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;Now, if you have some experience with Laravel, you already know this &lt;code&gt;Project&lt;/code&gt; class is almost empty because it inherits all of its properties and methods from the &lt;code&gt;Model&lt;/code&gt; abstract class.&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;Model&lt;/code&gt; class we go!  &lt;/p&gt;
&lt;h2&gt;
  
  
  The Model Class
&lt;/h2&gt;

&lt;p&gt;Once here we can see that this abstract class implements a lot of interfaces and uses a good number of traits, but we are looking for a specific method: &lt;code&gt;orderByDesc&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;So we open the find window, type our string and find… nothing.&lt;/p&gt;

&lt;p&gt;The method is not defined in this class. We can search inside every trait but without results. Seems like the &lt;code&gt;orderByDesc&lt;/code&gt; method is non-existent.&lt;/p&gt;

&lt;p&gt;Every good developer should now think: how is this possible?&lt;/p&gt;

&lt;p&gt;The answer lies in the &lt;code&gt;ForwardsCalls&lt;/code&gt; trait, &lt;strong&gt;PHP Magic Methods&lt;/strong&gt; (&lt;code&gt;__call&lt;/code&gt; and &lt;code&gt;__callStatic&lt;/code&gt;), and in the &lt;strong&gt;Late Binding&lt;/strong&gt;!&lt;br&gt;
In the first part of this series, Giuliano did a great job explaining how to re-create this pattern with a couple of classes in plain PHP, so I will not repeat what he already said.&lt;/p&gt;

&lt;p&gt;Long story short: the &lt;code&gt;Model&lt;/code&gt; class makes use of the &lt;code&gt;ForwardsCalls&lt;/code&gt; trait (you can see that just by opening the class).&lt;br&gt;
If you start to explore this class you will find both the &lt;code&gt;__call&lt;/code&gt; and &lt;code&gt;__callStatic&lt;/code&gt; methods and see the &lt;code&gt;__callStatic&lt;/code&gt; method do a Late Binding to invoke the requested method as non-static:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;static&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nv"&gt;$method&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mf"&gt;...&lt;/span&gt;&lt;span class="nv"&gt;$parameters&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way every static method not defined inside the &lt;code&gt;Model&lt;/code&gt; class will be redirected to a non-static method (still not defined in this class) and will trigger the &lt;code&gt;__call&lt;/code&gt; magic method.&lt;/p&gt;

&lt;p&gt;Inside the &lt;code&gt;__call&lt;/code&gt; magic method we can see a couple of if-blocks, but what we are looking for is the last line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;forwardCallTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;newQuery&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nv"&gt;$method&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$parameters&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What’s going on here?&lt;/p&gt;

&lt;h2&gt;
  
  
  The ForwardsCalls trait
&lt;/h2&gt;

&lt;p&gt;The previous code is calling the &lt;code&gt;forwardCallTo&lt;/code&gt; method, defined inside the &lt;code&gt;ForwardsCalls&lt;/code&gt; trait (&lt;em&gt;what a surprise!&lt;/em&gt;), passing along 3 parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the first is a &lt;code&gt;Query Builder&lt;/code&gt; instance (where the &lt;code&gt;orderByDesc&lt;/code&gt; method is defined!)&lt;/li&gt;
&lt;li&gt;the second is the name of the method we invoked (again, &lt;code&gt;orderByDesc&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;the third is the parameters we used (&lt;code&gt;'id'&lt;/code&gt; in the previous example)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now is the right moment to ask: why didn’t the developers keep using the more straightforward &lt;code&gt;call_user_func_array&lt;/code&gt; method?&lt;/p&gt;

&lt;p&gt;There are a good number of reasons understandable by looking at the &lt;code&gt;ForwardsCalls&lt;/code&gt; trait:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the framework has better exception management (look at how the exceptions are handled inside this trait)&lt;/li&gt;
&lt;li&gt;the framework has more flexibility (look at both &lt;code&gt;forwardCallTo&lt;/code&gt; and &lt;code&gt;forwardDecoratedCallTo&lt;/code&gt; methods)&lt;/li&gt;
&lt;li&gt;the developers avoid code repetition inside every class (they just need to use the trait and write a couple of lines for the magic methods)&lt;/li&gt;
&lt;li&gt;and more...&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is a great example of a developer-friendly pattern 🙂&lt;/p&gt;

&lt;h3&gt;
  
  
  Digging deeper
&lt;/h3&gt;

&lt;p&gt;How could we take advantage of this pattern?&lt;br&gt;
It's time to put our hands on some code!&lt;/p&gt;

&lt;p&gt;Just imagine this scenario: you are developing an e-commerce and now you have the need to export your data in various formats (i.e. XML and CSV).&lt;br&gt;
Because you don't need a UI to get these exports, you will create an Artisan Command to run your code right from the terminal.&lt;/p&gt;
&lt;h4&gt;
  
  
  Pre-requisite: ExportData - part one
&lt;/h4&gt;

&lt;p&gt;Don't be scared if you are not familiar with the creation of Artisan Commands: the code is super simple and you don't need to understand it to follow this tutorial.&lt;br&gt;
To keep things even more simple our export classes will not really export data. &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE&lt;br&gt;
If you want to learn about Artisan Commands check out the corresponding section inside the &lt;a href="https://laravel.com/docs/9.x/artisan" rel="noopener noreferrer"&gt;Laravel documentation&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;To create a new command we just need to run:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan make:command ExportData
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command will create the &lt;code&gt;ExportData&lt;/code&gt; class inside &lt;code&gt;app\Console\Commands&lt;/code&gt;.&lt;br&gt;
Looking at the code we can clearly see two properties and the &lt;code&gt;handle&lt;/code&gt; method. Maybe another time I will better explain how Artisan Commands works, but it's not the point of this article.&lt;/p&gt;

&lt;p&gt;Quoting directly from the documentation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;After generating your command, you should define appropriate values for the &lt;code&gt;signature&lt;/code&gt; and &lt;code&gt;description&lt;/code&gt; properties of the class. These properties will be used when displaying your command on the &lt;code&gt;list&lt;/code&gt; screen. The &lt;code&gt;signature&lt;/code&gt; property also allows you to define &lt;a href="https://laravel.com/docs/10.x/artisan#defining-input-expectations" rel="noopener noreferrer"&gt;your command's input expectations&lt;/a&gt;. The &lt;code&gt;handle&lt;/code&gt; method will be called when your command is executed. You may place your command logic in this method.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So let's copy this code for the &lt;code&gt;$signature&lt;/code&gt; property:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$signature&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'data:export
                        {type : The export format: XML, CSV}
                        {class : The class to export: Product, User}'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this is for the &lt;code&gt;$description&lt;/code&gt; property:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="nv"&gt;$description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'Export selected data in the given format'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the &lt;code&gt;handle&lt;/code&gt; method we will &lt;code&gt;echo&lt;/code&gt; the sentence &lt;code&gt;"it works"&lt;/code&gt; and test everything running the command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan data:export xml product
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you see &lt;code&gt;it works&lt;/code&gt; in the terminal, great! You just successfully ran your custom command!&lt;br&gt;
Now it's time to create the export logic and make use of the &lt;code&gt;ForwardsCalls&lt;/code&gt; trait.&lt;/p&gt;
&lt;h4&gt;
  
  
  The Exporter Logic
&lt;/h4&gt;

&lt;p&gt;Our exporter will be structured this way:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The main &lt;code&gt;ExportManager&lt;/code&gt; class, taking care of the general logic&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;IExporter&lt;/code&gt; interface, defining how the single exporter is implemented&lt;/li&gt;
&lt;li&gt;A couple of classes for the exporter logic: &lt;code&gt;CsvExporter&lt;/code&gt; and &lt;code&gt;XmlExporter&lt;/code&gt; implementing &lt;code&gt;IExporter&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;All these classes are placed inside &lt;code&gt;app\Support&lt;/code&gt; (the full project is available on &lt;a href="https://github.com/DonnieRich/file-exporter-app" rel="noopener noreferrer"&gt;GitHub&lt;/a&gt;).&lt;br&gt;
How do they work?&lt;/p&gt;
&lt;h5&gt;
  
  
  ExportManager
&lt;/h5&gt;

&lt;p&gt;The &lt;code&gt;ExportManager&lt;/code&gt; use the &lt;code&gt;ForwardsCalls&lt;/code&gt; to redirect most of the calls to the dedicated exporter class.&lt;br&gt;
Inside this class, you can see both &lt;code&gt;__call&lt;/code&gt; and &lt;code&gt;__callStatic&lt;/code&gt; magic methods, a couple of static methods (&lt;code&gt;list&lt;/code&gt; and &lt;code&gt;sendExport&lt;/code&gt;), and the private method &lt;code&gt;getExporter&lt;/code&gt;.&lt;br&gt;
If you read the first part of this article's series you are already familiar with how these magic methods work.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;__call&lt;/code&gt; method gets the &lt;em&gt;type&lt;/em&gt; and &lt;em&gt;model&lt;/em&gt; from the &lt;code&gt;$parameters&lt;/code&gt; array and capitalizes them (i.e. &lt;code&gt;xml&lt;/code&gt; -&amp;gt; &lt;code&gt;Xml&lt;/code&gt;, &lt;code&gt;PRODUCT&lt;/code&gt; -&amp;gt; &lt;code&gt;Product&lt;/code&gt;).&lt;br&gt;
After that it calls the &lt;code&gt;forwardCallTo&lt;/code&gt; method, passing an instance of the selected Exporter, the &lt;code&gt;$method&lt;/code&gt; called by our code, and the &lt;code&gt;$parameters&lt;/code&gt; array (just in case we should need it).&lt;/p&gt;

&lt;p&gt;To get the correct Exporter instance (i.e. &lt;code&gt;CsvExporter&lt;/code&gt;, &lt;code&gt;XmlExporter&lt;/code&gt;, etc...) the &lt;code&gt;ExportManager&lt;/code&gt; use the &lt;code&gt;getExporter&lt;/code&gt; method.&lt;br&gt;
This method returns an instance created dynamically from both &lt;code&gt;$type&lt;/code&gt; and &lt;code&gt;$model&lt;/code&gt; parameters.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cd"&gt;/**
 * Create an exporter instance
 * 
 * @param string $type the Exporter type (i.e. Csv)
 * @param string $model the model to use in the export (i.e. Product)
 * 
 * @return mixed an instance of the exporter (i.e. CsvExporter, XmlExporter, etc...)
 */&lt;/span&gt;
&lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getExporter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nv"&gt;$model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

        &lt;span class="c1"&gt;// $type = Csv -&amp;gt; App\Support\Exporters\CsvExoporter&lt;/span&gt;
        &lt;span class="nv"&gt;$exporter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"App&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;Support&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;Exporters&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$type&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;Exporter"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// $model = Product -&amp;gt; App\Models\Product&lt;/span&gt;
        &lt;span class="nv"&gt;$data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"App&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="s2"&gt;Models&lt;/span&gt;&lt;span class="se"&gt;\\&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$model&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="c1"&gt;// new App\Support\Exporters\CsvExoporter(App\Models\Product)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nv"&gt;$exporter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$data&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Error&lt;/span&gt; &lt;span class="o"&gt;|&lt;/span&gt; &lt;span class="nc"&gt;Exception&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nv"&gt;$e&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This way we get the instance of the export, initialized with the model it will use to get the data from the database.&lt;br&gt;
The &lt;code&gt;ExportManager&lt;/code&gt; class act both as a manager for the exports (it can list them or send a particular report to the administrator) and as a switch to call the class needed for the selected type of export (using the &lt;em&gt;Dynamic Class Instantiation&lt;/em&gt;).&lt;/p&gt;
&lt;h5&gt;
  
  
  IExporter, CsvExporter, XmlExporter
&lt;/h5&gt;

&lt;p&gt;The &lt;code&gt;IExporter&lt;/code&gt; interface allows us to create code that specifies which methods the &lt;em&gt;exporters&lt;/em&gt; must implement, without having to define how these methods are implemented:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="nc"&gt;IExporter&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * Get the data from the model and prepare the export
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;prepareExport&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Create the export
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;export&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Save the export inside the database
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using an &lt;code&gt;interface&lt;/code&gt; we define the basic standard for all the &lt;em&gt;exporters&lt;/em&gt; we will create, allowing us to create objects of different classes that may be used interchangeably because they implement the same interface.&lt;br&gt;
This is what we want for all our current and future &lt;em&gt;exporters&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Now let's take a look at one of the exporters (for the sake of simplicity both the exporters do almost the same things, but of course, they can do different operations).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;CsvExporter&lt;/span&gt; &lt;span class="kd"&gt;implements&lt;/span&gt; &lt;span class="nc"&gt;IExporter&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="nv"&gt;$filetype&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"CSV"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$items&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="nv"&gt;$model&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nv"&gt;$lastExportId&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;__construct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$_model&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$_model&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;prepareExport&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Preparing export of "&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="nb"&gt;get_class&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;export&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;prepareExport&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;items&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; records exported in "&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nv"&gt;$filetype&lt;/span&gt; &lt;span class="mf"&gt;.&lt;/span&gt; &lt;span class="s2"&gt;" format"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;lastExportId&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1305&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Export n. &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;lastExportId&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; saved inside database"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Feel free to download the example project and add your custom exporter! Get your hands dirty it's a great way to wrap your head around this kind of pattern.&lt;/p&gt;

&lt;p&gt;Remember to create a DB and run all the migrations and seeder before running the &lt;code&gt;data:export&lt;/code&gt; command.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Basically, every exporter is instantiated with a model, use this model to get all the records and simulate a DB writing.&lt;br&gt;
The &lt;code&gt;export&lt;/code&gt; and &lt;code&gt;save&lt;/code&gt; methods return an instance of the export class so that we can chain the methods calls and also get the instance in our &lt;code&gt;DataExport&lt;/code&gt; class.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;NOTE&lt;br&gt;
We get the exporter instance (&lt;code&gt;CsvExporter&lt;/code&gt;, &lt;code&gt;XmlExporter&lt;/code&gt;, etc...) because we are using the &lt;code&gt;forwardCallTo&lt;/code&gt; method inside &lt;code&gt;__call&lt;/code&gt; in our &lt;code&gt;ExportManager&lt;/code&gt; class.&lt;/p&gt;

&lt;p&gt;If we had used the &lt;code&gt;forwardDecoratedCallTo&lt;/code&gt; method, we would have got an instance of &lt;code&gt;ExportManager&lt;/code&gt;. Try it!&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;With all this logic out of the way we have only one more thing to do: add the correct code in the &lt;code&gt;DataExport&lt;/code&gt; &lt;code&gt;handle&lt;/code&gt; method.&lt;/p&gt;
&lt;h5&gt;
  
  
  ExportData - part two
&lt;/h5&gt;

&lt;p&gt;Remember our &lt;code&gt;handle&lt;/code&gt; method that does nothing more than echo &lt;code&gt;"it works"&lt;/code&gt;? It's time to make it work for real!&lt;br&gt;
We need to import the &lt;code&gt;ExportManager&lt;/code&gt; class by writing &lt;code&gt;use App\Support\ExportManager;&lt;/code&gt; before the class definition.&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;handle&lt;/code&gt; method we can now call the &lt;code&gt;export&lt;/code&gt; method on the &lt;code&gt;ExportManager&lt;/code&gt; (even if it's defined on the specific exporter) and get the correct instance.&lt;br&gt;
With this instance we can then call &lt;code&gt;sendReport&lt;/code&gt;, pass it the ID of the export we just created, and have it sent to the administrator inbox.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;handle&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$export&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ExportManager&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;export&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'type'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;argument&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'class'&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;save&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nc"&gt;ExportManager&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;sendExport&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$export&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;lastExportId&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h5&gt;
  
  
  Run the command
&lt;/h5&gt;

&lt;p&gt;Finally, you can test if everything it's working by running this command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;php artisan export:data csv product
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Our data is exported in the format we want! Yay!&lt;br&gt;
The logic we implemented allowed us to create a very flexible exporter: we can export all the &lt;code&gt;Models&lt;/code&gt; defined in our Laravel application and should we need a different kind of exporter (i.e. &lt;code&gt;PdfExporter&lt;/code&gt;, &lt;code&gt;ExcelExporter&lt;/code&gt;, etc...) we just need to create a new class caring only about the exporting logic and nothing more!&lt;/p&gt;

&lt;h2&gt;
  
  
  In conclusion
&lt;/h2&gt;

&lt;p&gt;It was a wild ride, wasn't it?&lt;br&gt;
I hope this helped you better understand one of the gems hidden inside the Laravel Framework!&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;ForwardsCalls&lt;/code&gt; trait gives us a powerful pattern to leverage when developing inside a Laravel application. It gives us a lot of flexibility and the possibility to keep our classes clean, well defined but still able to communicate.&lt;/p&gt;

&lt;p&gt;Giuliano also showed us how to bring this pattern outside Laravel and use it virtually in every PHP project we want.&lt;/p&gt;

&lt;p&gt;I enjoyed writing this article's series with Giuliano and I really hope this article inspired you to dig a little bit inside the code of the libraries and frameworks you use.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/giuliano1993/the-power-of-magic-methods-and-late-static-binding-4bj3"&gt;Here&lt;/a&gt; you can find the first half made by Giuliano. ;)&lt;/p&gt;

&lt;p&gt;If this article was helpful or want to start a conversation, feel free to reach out in the comments or here &lt;a href="https://twitter.com/gosty93" rel="noopener noreferrer"&gt;@gosty93&lt;/a&gt; and &lt;a href="https://www.linkedin.com/in/donato-riccio-wda/" rel="noopener noreferrer"&gt;@donato-riccio-wda&lt;/a&gt;&lt;br&gt;
We'll be happy to receive any feedback or ideas for future articles and tutorials.&lt;br&gt;
Happy Coding | _ 0&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This is the earliest version you could find on their public repository&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>php</category>
      <category>laravel</category>
      <category>programming</category>
      <category>oop</category>
    </item>
  </channel>
</rss>
