How to get a JS.ORG subdomain served through a gh-pages branch
Tags: github, tutorial
Published: 2019-11-14 21:41:15

[JS.org](http://js.org) is a free service started by [Stefan Keim](https://github.com/indus) in 2015 that provides custom subdomains for your GitHub Pages. What I especially love about the service is that it makes it easy for users of your projects to remember the URL...in my case I have a library called [Handsfree.js](https://github.com/handsfreejs/handsfree) hosted on [handsfree.js.org](https://handsfree.js.org)!

The easiest way to do this is to follow [their setup guide](https://github.com/js-org/js.org), but in this topic I'll take things further by explaining how to create an NPM script that commits your build directory to a `gh-pages` branch on the same repo.

## Step 1 - Naming your repo

In order for this to work, your desired subdomain must match your username or project name exactly ([see exceptions](https://github.com/js-org/js.org/wiki/Subdomain-Determination)). If you have a project located at `github.com/username/project` then the subdomain could be `username.js.org` or `project.js.org`. 

## Step 2: Add a CNAME

The next step is to add a file called `CNAME` (no extension) to the root of your project's build directory. A CNAME maps a GitHub Pages domains to a custom domain.

Inside the `CNAME`, add a single line with the .js.org subdomain you'd like:

```
    project.js.org
```

Here's a sample project directory:

```bash
    .gitignore
    dist/            <---- Build directory
      |- js/
      |- index.html
      |- CNAME       <---- Contains "project.js.org"
    src/
    package.json
```

## Step 3: Commit build directory to `gh-pages`

The next step is to commit your build directory to a `gh-pages` branch. This is a special branch that when committed to will expose its contents at  `username.github.io/project`. Because we have a `CNAME` in there, it'll tell GitHub to use that domain instead.

## Step 4: Make a Pull Request to the js.org repo

The final step is to [make a pull request to the js.org repo](https://github.com/js-org/js.org/blob/master/cnames_active.js). Simply add a new line to that file, where the key is your project name and the value is the subdomain you added in the `CNAME`. In our case it would be:

```js
    {
      ...
      "project": "project.js.org"
      ...
    }
```

## Bonus Step - npm script

If you've followed the steps so far, you'll see your project live at the `project.js.org` in around 24 hours!

However, because we are serving out of the `/dist` folder you'll quickly discover that you have to `cd` into your `/dist` folder each time, add your CNAME, and commit it to the `gh-pages` branch. That's really annoying and so the following steps will help automate that.

First, add the `shell` package to your projects `devDependencies` with  `npm install -D shelljs`. This will help us automate the terminal commands we would normally use to deploy from the `dist` folder.

Next, open your project's `package.json` file and add the following script:

```js
    {
      "scripts: {
        ...
        "deploy": "node deploy.js"
        ...
      }
    }
```

Then add a file named `deploy.js` to your projects root. This script will:

- Navigate to your build directory
- Create a CNAME record for you with your JS.org subdomain
- Commit the contents of your build directory to the `gh-branch` of your

```js
    /**
     * Helper script for building and deploying
     * Deploys out of /dist/
     */
    
    // Change these to match your Repo URL and the js.org domain
    const gitRepo = "https://github.com/username/project"
    const domainName = "project.js.org"
    const distPath = "dist"
    
    // build
    const pkg = require('./package.json')
    const shell = require('shelljs')
    
    // navigate into the build output directory
    shell.cd(distPath)
    
    // Create the CNAME and commit the directory
    shell.exec(`echo ${domainName} > CNAME`)
    shell.exec('git init')
    shell.exec('git add -A')
    shell.exec(`git commit -m "deploy docs for ${pkg.version}"`)
    
    // Push the project to the gh-pages branch
    shell.exec(`git remote add origin ${gitRepo}`)
    shell.exec('git push origin master:gh-pages -f')
    
    shell.cd('-')
```

Now, whenever you build your project you can just run `npm run deploy` to deploy your build directory to your new js.org domain, even if the build directory itself .gitignored!

## Gotchas

There are a few gotchas with using JS.org:

- You don't own the subdomain
- If a more popular project comes along with the same name, [it's possible that they can take it](https://github.com/js-org/js.org/wiki/Naming-Conflicts)

## Thanks for reading!

In this topic we learned how get a [js.org](http://js.org) subdomain, which pulls its contents from our build directory. We also explored an automation script to commit our build directory to the project's `gh-branch`.

Let me know if you get stuck at any stage, this was a bit tricky for me to figure out but in my opinion is definitely worth it!