Share your project with a Public URL using NPM
Tags: node, npm, javascript, typescript
Published: 2021-10-12 10:02:56

#### Introduction
This tutorial will show you how use `npm` to get a public URL for your project.

By the end of this tutorial, you'll be able to run `npm run expose` which will both start your app and give it a public URL.

In most cases, you won't need to do any firewall or networking config to make this work, because the traffic to the public URLs will automatically be tunneled through most networks and firewalls.

#### Prerequisites
- NodeJS. It comes with `npm` bundled in
- A Linux, Mac or Windows machine with access to the internet
- Half an hour or so of your time

You should be able to get a Public URL even if you are on a corporate network, VPN or behind a firewall (caveat: If its a very paranoid firewall, this may not work, for example if you work for a big three letter government agency or another extremely security sensitive employer and you are trying this at their office. Try at home to be sure in this case).

#### Set up your project
Open up your `package.json` file. If there is no `package.json` file (brand new project?), create one with `npm init` and follow the prompts.

You should have an entry in `package.json` for a `"start"` script. It should look like this:
```
{
    "name": "Your Project",
    "dependencies": {
        "react": "17.0"
        ....
    },
    "scripts": {
        "start: "<command to start your app>, i.e. node src/index.js"
    }
}
```

If not, you should create one. It should look like `"start": "<command to start your app>"` . Replace `<command to start your project>` with the command you use to start your app, such as `node src/index.js` if you use `express` and have it set up in `src/index.js`, or `react-scripts start` for react projects created using `create-react-app`.

You can now run `npm start` to start your app using `npm`. Thats useful even without a Public URL because you don't need to remember the command to start your app.

#### Find out what port number your app is listening on
You need to find out the port number your app is listening on. There are a few ways you can do this.

You can run `npm start`. Usually the port number will be shown in the output. You might see output like `127.0.0.1:3000` or `localhost:3000`. The port number is the number after `:`, in this example output it would be port `3000`.

In `express`, look for `app.listen`. It will have the port number passed as a parameter.
For React apps, the default port is `3000` if you used `create-react-app`, unless you've changed it.

If the port number is not the common port numbers of `80` or `443`, it will be in the last part of the URL you normally use when accessing your app locally, after the last `:` i.e. for `http://myapp.local:8000`, the port number is `8000`.

If there is no port number in the URL and the URL does not start with `https`, your app is running on port `80`, which is the default port that HTTP clients such as web browsers use so it doesn't need to be specified in URLs.

If the URL does start with `https` and there is no port number in the URL, the port number is `443`, which is the default HTTPS/SSL port.

#### Install [`expose`](https://expose.sh/install?utm_source=dev.to&utm_campaign=share-public-url-npm)
There is one dependency we need to satisfy before we continue. As `npm` is just a dependency manager that relies on other software to provide most functionality (such as `npm` dependencies), it can't get you a public URL by itself without extra help.

For this tutorial, you'll need to install [`expose`](https://expose.sh/install?utm_source=dev.to&utm_campaign=share-public-url-npm), an app I created specifically for this purpose. You can then configure `npm` to use it to generate public URLs.

The process to install [`expose`](https://expose.sh/install?utm_source=dev.to&utm_campaign=share-public-url-npm) is a bit different, but just as easy as installing an NPM dependency.

Go to [https://expose.sh/install](https://expose.sh/install?utm_source=dev.to&utm_campaign=share-public-url-npm) for instructions to install [`expose`](https://expose.sh/install?utm_source=dev.to&utm_campaign=share-public-url-npm).  Its an easy one line copy and paste install for Linux and Mac, just copy and paste the code shown into a terminal.

A downloadable executable is available for Windows, which you will then need to copy somewhere in your [PATH](https://helpdeskgeek.com/windows-10/add-windows-path-environment-variable/), such as `C:\Windows\System32`  using an account with Administrator permissons.

#### Add [`expose`](https://expose.sh/install?utm_source=dev.to&utm_campaign=share-public-url-npm) to NPM
Adding [`expose`](https://expose.sh/install?utm_source=dev.to&utm_campaign=share-public-url-npm) to `npm` is a bit different to adding other dependencies.

Normally when adding dependencies to `npm` you would add them to the `"dependencies"` or `"devDependencies"` section in `package.json` or run `npm install`. This would work for dependencies like libraries, but [`expose`](https://expose.sh/install?utm_source=dev.to&utm_campaign=share-public-url-npm) is a separate app, kind of like `grunt` or `webpack` which are often installed globally.

So in this case, we'll add an entry to the `"scripts"` section in `package.json` because we are going to use `npm` to launch your app with the `"start"` script you created earlier and then launch [`expose`](https://expose.sh/install?utm_source=dev.to&utm_campaign=share-public-url-npm), which will give your app a Public URL. This is similar to how other projects often run `grunt` or `webpack` before starting the app.

In `package.json`, look for the `"scripts"` section. If there isn't one, create it.

Add this entry to the scripts section: `"expose": "npm start & expose <insert your port number here and remove the arrows>"`;

For example, lets say my app listens on port `3000`, like most React apps. My `package.json` file should look something like this:
```
{
    "name": "Your Project",
    "description": "The project you want to get a public URL for"
    "dependencies": {
        "react": "17.0"
        ....
    },
    "scripts": {
        "expose": "npm start & expose 3000"
    }
}
```

This script will start your app, then run [`expose`](https://expose.sh/install?utm_source=dev.to&utm_campaign=share-public-url-npm) to give your app a Public URL.

#### Expose your app
Now run `npm run expose`.

You'll see something similar to this in the output:
```
http://siiqwa.expose.sh is forwarding to localhost:3000
https://siiqwa.expose.sh is forwarding to localhost:3000
```

These public HTTP and HTTPS URLs are randomly generated. Hit them in a browser or any other HTTP client and the traffic will go to your locally running project. All traffic is passed from the [https://expose.sh](https://expose.sh?utm_source=dev.to&utm_campaign=share-public-url-npm) service to the the [`expose`](https://expose.sh/install?utm_source=dev.to&utm_campaign=share-public-url-npm) client app, which is why you didn't have to do any complex networking or firewall config.

Traffic to the public URLs can easily tunnel through most corporate firewalls and networks.

You can also run [`expose`](https://expose.sh/install?utm_source=dev.to&utm_campaign=share-public-url-npm) by itself for non node applications. For example `expose 3000` will also create Public URLs, except you will need to run `npm start` first otherwise the connections won't reach your app.

Randomly generated URLs are good to get started. They are public, so you can share them around with colleagues and friends. They should be accessible from any unrestricted internet connection in the world. Some things they might be useful for:

* You're building a mobile app backend and want to connect to it from the app on your mobile device. Rather than plug a cable into your phone, configure USB debugging or do other complex config, you can expose your backend API with a public URL, then configure your mobile app to use this. No cables needed.

* Webhook integrations. With a public URL a webhook provider can send a request directly to your locally running project, enabling you quickly test changes and use tools like debuggers to speed up development.

* Local HTTPs. Normally to get HTTPs locally you need to buy a certificate and configure your web server to use it. Since you now have a https URL, you don't need to do this unless you really want to. HTTPS is required for certain features like Web Notifications and Progressive Web Apps.

* Collaborative development. Maybe you're building a back end API and your colleague is building the React App that will use it, or vice versa. You can both generate public URLs for your projects and use them to integrate your work with each other or even other squad members. Feedback will be faster than deploying code to a remote server because you and your collaborators wont need to wait for deployments.

* Demos. You can use the URL to demo your project to a colleague or someone else, just send them the URL.

More use cases and cookbooks can be found in the [`expose`](https://expose.sh/install?utm_source=dev.to&utm_campaign=share-public-url-npm) documentation: [https://expose.sh/docs/](https://expose.sh/docs?utm_source=dev.to&utm_campaign=share-public-url-npm)

#### Getting a custom URL that does not change
Because [`expose`](https://expose.sh/install?utm_source=dev.to&utm_campaign=share-public-url-npm) by default generates random subdomains, using a custom subdomain (like `myapi.expose.sh`) would save you from needing to reconfigure a different endpoint every time you run [`expose`](https://expose.sh/install?utm_source=dev.to&utm_campaign=share-public-url-npm).

Expose.sh is free to use for randomly generated subdomains. If you want to use your own custom subdomains like `myreactapp.expose.sh`, you can do this for as little as $5.99/month depending on how many domains you want to use. This also supports the [`expose`](https://expose.sh/install?utm_source=dev.to&utm_campaign=share-public-url-npm) service, which is run by an independent developer and doesn't have a big company behind it.

Here's an example `package.json` using a custom subdomain.
```
{
	"name": "Your Project",
	"description": "The project you want to get a public URL for"
	"dependencies": {
		"react": "17.0"
		....
	},
	"scripts": {
		"expose": "expose 3000 as myreactapp.expose.sh"
	}
}
```

With this config, running `npm run expose` will now expose your project under the URL `myreactapp.expose.sh` (assuming no one else has taken that subdomain):
```
https://myreactapp.expose.sh is forwarding to localhost:3000
http://myreactapp.expose.sh is forwarding to localhost:3000
```

Of course, you can also run [`expose`](https://expose.sh/install?utm_source=dev.to&utm_campaign=share-public-url-npm) by itself without `npm`. In this example you can run `expose 3000 as myreactapp.expose.sh`, but you'll need to run `npm start` first otherwise the traffic hitting the Public URLs won't reach your app because it won't be running.

You can [Sign up here](https://dashboard.expose.sh?utm_source=dev.to&utm_campaign=share-public-url-npm) to get custom subdomains.

#### Limits
The Public URLs expire after several hours. They should be used for development but not for any apps in production. Don't use them to do anything involving extreme amounts of traffic like load testing, but serving an app or API is fine.

#### Conclusion
`npm` scripts are useful for testing and building your app, now you can also use them to get a public URL.

As an independent developer, I don't have a big marketing department or investor funding to help me spread the word about `expose`. So if you found this article useful, please share it around on your favourite social platforms like Facebook, Twitter and LinkedIn.

Also consider purchasing a subscription to help cover the costs of running the [`expose`](https://expose.sh/install?utm_source=dev.to&utm_campaign=share-public-url-npm) service.

Happy coding!