newww
We're using Hapi as our framework for the npm website. We wrote all about why we chose Hapi in a blog
post.
If you'd like to contribute to this project,
please do!
Application Structure
Let's take a tour of the app.
Assets
The assets directory contains all the frontend stuff: JavaScript, stylesheets, images, fonts, robots.txt, favicon.ico, etc. The gulp process watches this directory for file changes, and outputs everything to the static directory, which is ignored by git to prevent automated version control noise.
Styles
We're using Stylus, a CSS preprocessor with clean syntax and all the bells and whistles one would expect from a CSS preprocessor like variables, mixins, color manipulation functions, autoprefixing, etc. It's less of a hassle than Sass because it doesn't have C or Ruby dependencies.
assets/styles/index.styl is the master stylesheet, which is converted by the gulp process to static/styles/index.css.
For more information, see the style guide.
Templates
We're using Handlebars as our templating engine. Server-rendered templates live in templates. Frontend templates live in assets/templates. They are browserified into the bundled JS file using the hbsfy
transform.
Partials
Handlebars partials are handy for markup that is needed in more than one place. All the partials are located in templates/partials. Every .hbs
file in the partials directory becomes avaiable in all handlebars templates. For a good explanation of how to use partials, check out Passing variables through handlebars partial on Stack Overflow, or search for {{>
in this codebase to see how we're using them.
Locales
A rudimentary localization effort is under way. The locales directory contains javascript files that export translations of various strings used throughout the app.
Content Security Policy (CSP)
We use the blankie Hapi plugin to enforce a strict content security policy that disallows execution of unsafe Javascript. It's defined in csp.js.
Routes
Every route in the application is defined in routes.
Handlers
Handlers (sometimes called controllers) are functions that accept two parameters: request
and reply
.
The request
parameter is an object with details about the end user's request, such as path parameters, an associated payload, authentication information, headers, etc.
The second parameter, reply
, is the method used to respond to the request.
Here's an example of a simple handler:
server.route({
method: 'GET',
path: '/',
handler: function (request, reply) {
reply('Hello!');
}
});
The above handler is defined inline, but most of the handlers in this application are defined in their own file in the handlers directory.
Tests
We're using Lab as our testing utility and
Code for assertions.
npm install
npm test
If you have npm 2.0.0 or greater installed (which you should),
you can pass additional arguments to scripts. This handy feature
allows for more granular control of the tests you want to run:
npm test -- test/handlers
npm test -- test/models/user.js
Code
We're using semi-colons and comma-last. No rhyme or reason; just cuz.
Running the server locally
It is not currently possible for non-employees to run the development server. This is being tracked at github.com/npm/newww/issues/761.
redis-server&
cp .env.example .env
npm install
npm run dev
The server should be running at localhost:15443.
If you have any trouble getting the site running locally, please open an issue and we'll help you figure it out.
Environment variables
newww
uses many environment variables for configuration.
API Endpoints
BILLING_API
, the URL to the billing API serviceCANONICAL_HOST
, the canonical hostname users should visit for this serviceDOWNLOADS_API
, the URL of the downloads APIELASTICSEARCH_URL
, the URL to the elastic search database to use for searchLICENSE_API
, the URL to the license APIUSER_API
, the URL to the user-acl APICMS_API
, the URL to the npm v1 CMS API
Zendesk integration
ZENDESK_URI
, the URL to the Zendesk APIZENDESK_TOKEN
, the Zendesk access tokenZENDESK_USERNAME
, the Zendesk account username
Configuration
REDIS_URL
, the URL to a redis instance for this serviceSESSION_PASSWORD
, a password for sessionsSESSION_SALT
, a salt to randomize encryption of sessionsSESSION_COOKIE
, the cookie name for session IDsMAIL_ACCESS_KEY_ID
, the access key ID for sending mailMAIL_SECRET_ACCESS_KEY
, the secret key for sending mailUSE_CACHE
, ???
Marketing integration
HUBSPOT_FORM_NPME_SIGNUP
, uuid of a hubspot formHUBSPOT_FORM_NPME_AGREED_ULA
, uuid of a hubspot formHUBSPOT_FORM_NPME_CONTACT_ME
, uuid of a hubspot formHUBSPOT_FORM_PRIVATE_NPM, uuid of a hubspot form
HUBSPOT_FORM_PRIVATE_NPM_SIGNUP, uuid of a hubspot form
HUBSPOT_PORTAL_ID
, the hubspot portal IDMAILCHIMP_KEY
, the mailchimp key
Feature Flags
FEATURE_BYPASS_EMAIL_VERIFY
, users who can bypass email verification, for testingFEATURE_NPMO
, boolean, whether to run in npm On-site mode, which is a stripped-down configuration
Miscellaneous
NPME_PRODUCT_ID
, uuid of the npm On-site productNPMO_COBRAND
, the user's brand displayed in the npm On-site productCMS_CACHE_TIME
, in seconds, how long to cache CMS content without refetching