DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’» is a community of 963,673 amazing developers

We're a place where coders share, stay up-to-date and grow their careers.

Create account Log in
Monica Stevens
Monica Stevens

Posted on

Build & publish your own private npm package for free

Note: This is a real example, not a tutorial on how to print "hello world" with an npm package. So buckle up buckaroo. 🀠

Do you want to easily share code between projects? Do you want to keep that code private but avoid the monthly fee for privately publishing to npmjs dot com? Then this is the tutorial for you.

We'll be building an npm package, adding JavaScript and CSS, uploading to a private git repo on Bitbucket and making a simple project to test the package with.

Final product: https://github.com/mocasalter/npm-package-demo

When we're done your package will accessibly✨ hide outline focus styles for mouse users but show them for keyboard users*. Like this:

Button Outline Demo

Pre reqs

I assume that you know how to use the command line, have the npm CLI and NodeJs installed and know how to use them, and have git installed and have a decent grasp of how it works.

1. Start a new package

In your CLI, run these commands to make a new folder, navigate into that folder and initialize a new npm package.

mkdir smart-focus-ring
cd smart-focus-ring
npm init -y
Enter fullscreen mode Exit fullscreen mode

Make a new folder called lib and a new file called index.js. Index is the default entry point file for an npm package, and lib will hold the custom files.

mkdir lib
touch index.js
Enter fullscreen mode Exit fullscreen mode

Then open the smart-focus-ring folder in a text editor. If you have Visual Studio Code installed you can run the command $ code ..

Open package.json and add this files array. That will ensure the lib directory is downloaded whenever the package is installed.

{
  "otherStuff": "",
  "files": [
     "lib"
  ]
}
Enter fullscreen mode Exit fullscreen mode

2. Add JavaScript

Create a new file in lib called smart-focus-ring.js and paste in this code.

function handleFirstTab(e) {
  if (e.keyCode === 9) {
    // the "I am a keyboard user" key
    document.body.classList.add('user-is-tabbing');
    window.removeEventListener('keydown', handleFirstTab);
  }
}

function smartFocusRing() {
  window.addEventListener('keydown', handleFirstTab);
}

module.exports = smartFocusRing;
Enter fullscreen mode Exit fullscreen mode

It adds a class user-is-tabbing to the body when the user hits the tab key.

That last line module.exports exposes the smartFocusRing function as a module so we can use it in index.js.

3. Export the function

Now import smartFocusRing into index.js.

const smartFocusRing = require('./lib/smart-focus-ring.js');
module.exports = smartFocusRing;
Enter fullscreen mode Exit fullscreen mode

module.export-ing from the package's entry point (index.js) makes smartFocusRing available to any project that has installed the smart-focus-ring package.

4. Add CSS

Now add CSS to make the style changes based on whether the user-is-tabbing class is present on the body.

In the lib folder, add a new file called styles.css and paste in this code.

/* Hide the focus ring until we know it's needed */
button:focus,
input:focus,
select:focus,
textarea:focus {
    outline: none;
}

.user-is-tabbing button:focus,
.user-is-tabbing input:focus,
.user-is-tabbing select:focus,
.user-is-tabbing textarea:focus {
    outline: 2px solid #7aacfe !important; /* for non-webkit browsers */
    outline: 5px auto -webkit-focus-ring-color !important;
}
Enter fullscreen mode Exit fullscreen mode

Your directory should look like this.

└───lib
β”‚   β”‚   smart-focus-ring.js
β”‚   β”‚   styles.css
β”‚   index.js
β”‚   package.json
Enter fullscreen mode Exit fullscreen mode

5. Publish to Bitbucket

At this point you could publish to npm if you wanted to but there's a monthly fee for private packages so we'll use Bitbucket instead.

Run these commands to create a new repo inside the smart-focus-ring folder.

cd /path-to/smart-focus-ring
git init
git add .
git commit -m "Initial commit"
Enter fullscreen mode Exit fullscreen mode

Then create an account on bitbucket.org and a new, private git repo on Bitbucket.

Bitbucket's Create New Repo Screen

Run these commands to upload your local repo to Bitbucket.

git remote add origin git@bitbucket.org:YOURUSERNAME/smart-focus-ring.git
git push -u origin master
Enter fullscreen mode Exit fullscreen mode

And you'll see a warning that looks something like this.

Warning, permission denied

This is where things get interesting.

SSH keys

That warning comes up because you haven't given your computer permission to use your private Bitbucket repo yet. To do so, follow Atlassian's walk through on setting up SSH keys for Bitbucket for your operating system.

...Or if your privacy isn't that important, you can go to your Bitbucket repo, select Settings and uncheck the box for "This is a private repository."

Then run this command again and that warning should be gone.

git push -u origin master
Enter fullscreen mode Exit fullscreen mode

6. Make a test project

Create a new project folder, initialize npm and make some files.

mkdir tester-project
cd tester-project 
npm init -y
touch index.js
touch index.html
Enter fullscreen mode Exit fullscreen mode

Add some html to index.html.

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Tester Project</title>
    <style>
        body{font-family:"Open Sans",sans-serif;}
        button{border:none;border-radius:0;padding:0.65em 1.2em;cursor:pointer;color:#fff;background:#8d6e91;}
        button:focus{background:#AB90B2}
    </style>
</head>
<body>
    <h1>Tester Project</h1>
    <button type="button">button</button>
    <script src="index.js"></script>
</body>
</html>
Enter fullscreen mode Exit fullscreen mode

And install a bundler so we'll have ES6 module support.

npm install -g parcel-bundler
Enter fullscreen mode Exit fullscreen mode

Run the bundler and go to the url it gives you. Mine was localhost:1234.

parcel index.html
Enter fullscreen mode Exit fullscreen mode

Now try clicking the button. See how it has a focus ring? Once the package is installed, that focus ring will only show if you've indicated keyboard navigation by hitting the tab key.

Button with Outline

7. Import the module

Install the package using your Bitbucket user name.

npm i git+ssh://git@bitbucket.org:YOUR-USER-NAME/smart-focus-ring.git
Enter fullscreen mode Exit fullscreen mode

Import the smart-focus-ring assets into the index.js file and call the smartFocusRing function.

import smartFocusRing from 'smart-focus-ring';
import './node_modules/smart-focus-ring/lib/styles.css';
smartFocusRing();
Enter fullscreen mode Exit fullscreen mode

Then run Parcel and go to the url it provides.

parcel index.html
Enter fullscreen mode Exit fullscreen mode

Now if you click the button the focus ring will be gone, but it will appear when you hit the tab key. All thanks to your npm package! Congratulations! πŸ₯³

Button Outline Demo




*As seen in Removing that ugly :focus ring (and keeping it too).

Top comments (2)

Collapse
 
kushalmahajan profile image
Kushal V. Mahajan

I liked your post but the title is misleading. It's not a npm package. Instead of downloading from npm, we are downloading directly from code repository.

Collapse
 
wahabshah23 profile image
Abdul Wahab Shah

Exactly. The post title is misleading!

"I made 10x faster JSON.stringify() functions, even type safe"

☝️ Must read for JS devs