
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
tldr; Freshly baked Node + Koa, MVC app
frameworkboilerplate for rapidly building MVP's
Tip: While reading, you can click the Glazed logo in section headers to jump back to this index.
Glazed is an application framework boilerplate for rapid iteration of a minimal viable product.
Glazed was designed to prove the viability of an idea as quick as possible, with sheer simplicity, and extremely ambitious quality level. It uses the latest standards, best practices, and is production ready.
For example, Glazed can be used to release prototypes of the following in less than 30 days:
Glazed is more of a "boilerplate" than a "framework". It's often called a framework because of keyword search popularity and the confusion between the two words. It has a very minimal codebase, which was written with ES6/ES7 (yes, it uses the new Async/Await syntax!) – and it was structured according to some loose thoughts on an MVC approach.
Glazed does not use single page app ("SPA") client-side library, and does not use any special client-side framework by default (other than jQuery; though it can easily be changed to a SPA). The reason it does not use a SPA library, such as React or Angular, is because most (probably?) of software as a service start-ups (and API's in general) don't need something this fancy to start (API's don't even need a SPA). Using SPA frameworks will and have made proving the viability of an idea take even longer than it already should. Instead, Glazed uses the extremely powerful and fast rendering template language called Nunjucks. In order to render it with Koa, we use koa-nunjucks-promise.
Before diving into the structure and how it works, it is important to share that Glazed is highly opinionated and may not be for you. If you are not comfortable or do not agree with the ideas shared in these articles, then perhaps you should not read any further into Glazed, and close this browser tab.
Did you ship a project with Glazed? File an issue and we'll include it!.
To get you excited about using Glazed, here are projects built with it in less than a week each:
Its parent framework "Eskimo" was used to ship some very cool projects too!
Glazed is loosely-based on MVC design, and it has the following structure (tree output below):
.
├── History.md
├── LICENSE
├── Readme.md
├── VERSION
├── gulpfile.babel.js
├── package.json
├── .env.example
├── src
│ ├── app
│ │ ├── controllers
│ │ │ ├── app
│ │ │ │ └── index.js
│ │ │ └── index.js
│ │ ├── models
│ │ │ ├── plugins
│ │ │ │ └── common.js
│ │ │ └── user.js
│ │ └── views
│ │ ├── 404.html
│ │ ├── 500.html
│ │ ├── _footer.html
│ │ ├── _nav.html
│ │ ├── about.html
│ │ ├── admin.html
│ │ ├── home.html
│ │ ├── layout.html
│ │ └── my-account.html
│ ├── assets
│ │ ├── browserconfig.xml
│ │ ├── css
│ │ │ ├── _variables.scss
│ │ │ └── app.scss
│ │ ├── favicon.ico
│ │ ├── fonts
│ │ ├── img
│ │ │ ├── android-chrome-144x144.png
│ │ │ ├── android-chrome-192x192.png
│ │ │ ├── android-chrome-36x36.png
│ │ │ ├── android-chrome-48x48.png
│ │ │ ├── android-chrome-72x72.png
│ │ │ ├── android-chrome-96x96.png
│ │ │ ├── apple-touch-icon-114x114.png
│ │ │ ├── apple-touch-icon-120x120.png
│ │ │ ├── apple-touch-icon-144x144.png
│ │ │ ├── apple-touch-icon-152x152.png
│ │ │ ├── apple-touch-icon-180x180.png
│ │ │ ├── apple-touch-icon-57x57.png
│ │ │ ├── apple-touch-icon-60x60.png
│ │ │ ├── apple-touch-icon-72x72.png
│ │ │ ├── apple-touch-icon-76x76.png
│ │ │ ├── apple-touch-icon-precomposed.png
│ │ │ ├── apple-touch-icon.png
│ │ │ ├── favicon-16x16.png
│ │ │ ├── favicon-194x194.png
│ │ │ ├── favicon-32x32.png
│ │ │ ├── favicon-96x96.png
│ │ │ ├── mstile-144x144.png
│ │ │ ├── mstile-150x150.png
│ │ │ ├── mstile-310x150.png
│ │ │ ├── mstile-310x310.png
│ │ │ ├── mstile-70x70.png
│ │ │ └── safari-pinned-tab.svg
│ │ ├── js
│ │ │ └── flash.js
│ │ └── manifest.json
│ ├── config
│ │ ├── environments
│ │ │ ├── development.js
│ │ │ ├── index.js
│ │ │ ├── production.js
│ │ │ ├── staging.js
│ │ │ └── test.js
│ │ └── index.js
│ ├── helpers
│ │ ├── dynamic-view-helpers.js
│ │ ├── error-handler.js
│ │ ├── index.js
│ │ ├── passport.js
│ │ ├── policies.js
│ │ ├── render-page.js
│ │ └── sentry.js
│ ├── index.js
│ └── routes
│ └── index.js
└── test
├── mocha.opts
├── support
│ └── index.js
└── unit
└── server.test.js
We use Koa for the back-end, and if you previously used Express, you might want to understand the differences; see this article.
To rid of callback hell, we use a new JavaScript language feature called Async/Await.
For example, here are two blocks of code that compare before and after...
This is how one might write a Mongoose save with callbacks:
// find the user that belongs to the @glazed organization
// and make their user group have "admin" status
function updateUser(req, res, next) {
Users.findOne({ org: 'glazed' }, function(err, user) {
if (err) return next(err);
if (!user) return next(new Error('User does not exist'));
user.group = 'admin';
user.save(function(err, user) {
if (err) return next(err);
res.json(user);
});
});
}
This is how one might write a Mongoose save with Async/Await:
// find the user that belongs to the @glazed organization
// and make their user group have "admin" status
static async updateUser(ctx) {
let user = await User.findOne({ org: 'glazed' });
user.group = 'admin';
ctx.body = await user.save();
}
Glazed has custom built-in error handling – so actually you don't even need to wrap the Async/Await function with a
try {} catch (e) {}statement – but be careful, because in other cases you might want to!
Other scenarios where Async/Await is resourceful:
By default, the latest Bootstrap version 4 alpha is used (it uses SCSS for its CSS pre-processor).
However, you can swap out Bootstrap to another version, or entirely for something else. You can also switch SCSS to use LESS or plain CSS.
Also included are the front-end packages jQuery and Sweetalert.
You don't need Bower anymore, since you can simply import libraries through our Browserify setup!
Job scheduling is built on top of Agenda. See the src/agenda.js file and also src/jobs folder for how it works and is set up.
There is one sample job scheduler built-in, which is in the post('save') hook for when a user is created. The user gets a welcome email.
You can see the content and template of the email in the src/emails/welcome folder. Emails are sent using Postmark and the package email-templates.
MongoDB and Mongoose are built in, but you can swap them out with your preferred database and ORM glue. If you need help setting up Postgres and Bookshelf, then we suggest you to change your mind! It will slow you down – but if you insist, we can put you in the right direction.
To better beautify validation error messages we use mongoose-beautiful-unique-validation
To enhance security and allow you to have selective JSON output from query results (e.g. never return a user's refresh_token, access_token, hash, or password fields) we use mongoose-json-select.
We automatically strip the default provided tokens/hash/password fields from JSON output, don't worry! See the default user model in
app/models/user.jsfor insight.
Redis and Passport are used for session storage and authentication.
Out of the box, we provide (2) means of authentication for restricted routes:
api_token field is populated for each user in the database after their first log-in, and this can be passed as the user in user:pass with BasicAuth headers – password is blank for simplicity). This is very useful for API access if you are building an iOS/Android or client-side focused app. See the API Example below for more information on this and how to test it out.If you need to add additional strategies, you can literally clone the Google Strategy code and use another passport package for your auth provider. Don't be afraid to join our Slack channel and ask us for help!
Using the user's api_token field value (which is automatically generated upon user creation, see src/app/models/user.js), you can pass the test of the policy Policies.ensureApiToken.
For example, we have one restricted route built into Glazed, which is GET /v1/users.
As a test, try to sign in with Google OAuth at http://localhost:3000 once you start up the app.
Then, you can load the MongoDB cli with mongo and run the command use glazed_development and then db.users.findOne().api_token to get the value of the API token.
Take this value, and run the following curl command using it (replace it into where it says <apitoken> below:
curl -u "<apitoken>:" http://localhost:3000/v1/users
This should output a JSON response like the following:
{
"id": "578ee8af0d1f58b77a4f9ad7",
"updated_at": "2016-07-20T02:57:51.099Z",
"created_at": "2016-07-20T02:57:51.000Z",
"object": "user",
"display_name": "Nick Baugh",
"given_name": "Nick",
"family_name": "Baugh",
"google_profile_id": "105518868040745239689",
"avatar_url": "https://lh3.googleusercontent.com/-XdUIqdMkCWA/AAAAAAAAAAI/AAAAAAAAAAA/4252rscbv5M/photo.jpg"
}
With respect to security, we support the following out of the box:
Glazed uses the following helper libraries:
v6.0.0v2.x (or commonly referred to as @next)Through koa-livereload and gulp-livereload your assets automatically reload as you continually change and save them.
This means you can have your editor open and a browser tab opened to your app at http://localhost:3000/ – of course you need to be running the app with gulp watch – and your changes appear in real-time! Yes, we know this is not new technology, but not many other frameworks had this built-in (at least the right way with gulp).
For example, if you make the following change to your stylesheet file and save it...
body {
- background-color: red;
+ background-color: hotpink;
}
... then your background color on the browser tab will instantly change to hot pink.
Glazed comes with a robust and well-tested Gulpfile (written with Babel!). Check it out here.
What's a Gulpfile? You can read about Gulp here – but it's basically a file that has a series of build tasks defined (e.g. it's very similar to a Makefile).
In a production environment, your app's assets will be minified, compressed, gzipped, revision hashed, and uploaded to Amazon S3 and CloudFront for load balancing. To do this, we use the packages koa-manifest-rev and gulp-rev, with plugins that include:
import (or require) modules in the browser! You no longer need to use Bower. We looked at using Webpack when we had worked on React Native stuff, but it was too complicated and we ran into way too many problems..eslintrc configuration. Feel free to swap out our .eslintrc for something like eslint-config-airbnb.This is the de-facto standard for hosting images, fonts, scripts, and assets in general
– and it is managed properly in Glazed using asset revisioning. For example, your file
named glazed-logo.png will become glazed-logo-0775041dd4.png in production (you don't have to worry about cache busting!).
Not only that, but your files will be linted and they come with sourcemaps too!
To build and publish to AWS for production, follow these simple steps:
NODE_ENV=production gulp build
NODE_ENV=production gulp publish
You can test it out with NODE_ENV=production node app.
Is this cross-browser compatible? Yes, 100%! What about all of your ES6/ES7 code? Yes, 100%.
However, if you stick with the default v4 Bootstrap CSS framework – it only supports IE9+ and iOS 7+.
All of your code is converted to browser-friendly ES5 vanilla JavaScript (using Browserify and Babelify)...so it's cross-browser compatible!
This means both your server-side and client-side code is built to the
./lib/folder with ES5 syntax when the Gulpfile is run withgulp build. You never have to worry about passing some--harmonyflag either to run your app. The idea here is that you can focus on writing clean, short bits of code – and never have to worry about how it runs.
By default, all users are assigned to the "user" group. This group is defined in the user model under app/models/user.js per the property `'group'``.
This approach was inspired by classic Linux-based user-group permissioning.
We've also added a default policy helper to detect whether or not a user an admin, which you can add as a middleware before your controller logic.
For example, if you want to restrict access to all /admin routes, you can add this simple middleware:
router.all('/admin*', policies.ensureAdmin);
This simple middleware is automatically added by default for you.
If you'd like to grant yourself admin access to the /admin routes, then you can run this script (replace with your email address and database name):
mongo glazed_development --eval 'printjson(db.users.update({ email: "niftylettuce@gmail.com" }, { $set: { group: "admin" }}));'
Since we don't use a SPA, you don't have to worry about rendering SEO-friendly content! What you see in the browser is what the search engine crawler sees ("WYSIWTSEC" or something... haha)!
By default, we provide a simple to use configuration file that allows you to swap in page titles and descriptions for a majority of your routes.
For anything complex, you can customize them yourself by passing local variables title and description to views.
We didn't build in structured open graph tags as a default to edit, since we figure you can customize to your own.
With this setup, we have climbed to #1 on Google for various keywords, easily. Of course, you need great content and traffic!
In order to prevent duplicate content, we have added a plugin that removes trailing slashes from URL's, so /home/ will 301 redirect to /home automatically.
We built-in international localization/translation support!
See the following files for an understanding of how it works:
src/locales folder (full of all the translations, if a locale is missing, it defaults to English; en.json)src/config/locales.js file (uncommented languages are the ones supported)src/config/index.js (see the config.i18n.HELLO_WORLD variable, which you can use as your strings)Yes, you can customize this for international localization. But we didn't build this in by default. We're just letting you know we thought of it. If you want recommendations on services to use for this and how to integrate, then join our Slack and ask us!
For performance, you should always use the lean() method while writing your Mongoose queries.
You should also never use Mongoose hooks, virtuals, or the populate method.
If you need to asynchronously populate or waterfall chain population of database references, we suggest to use the $lookup operator or use Async/Await syntax to keep it clean.
For an example of how to write a populate() method with $lookup, see this GitHub issue.
We've also included these libraries to help with performance:
304 "Not Modified" header if condition matches)X-Response-Time with the number of milliseconds the server took to respondOther than that, you just need to increase your server storage/bandwidth/memory/swap, add load balancing, and/or use PM2's clustering mode – and you should be able to support thousands of users. Horizontal scaling!
Check out the deployment section below for how a production environment and deployment process should be configured.
You'll need to have the following installed on your operating system (we provide instructions below):
We also recommend that you install our preferred tools as well!
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
curl -o- https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash
source ~/.bashrc
nvm install v6.0.0
nvm alias default v6.0.0
launchctl after you hit ENTER):brew install mongo
launchctl after you hit ENTER):brew install redis
curl -o- https://raw.githubusercontent.com/creationix/nvm/master/install.sh | bash
source ~/.bashrc
nvm install v6.0.0
nvm alias default v6.0.0
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
echo "deb http://repo.mongodb.org/apt/ubuntu "$(lsb_release -sc)"/mongodb-org/3.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.0.list
sudo apt-get update
sudo apt-get install -y mongodb-org
service mongod status
sudo add-apt-repository ppa:chris-lea/redis-server
sudo apt-get update
sudo apt-get install redis-server
redis-benchmark -q -n 1000 -c 10 -P 5
source ~/.profile
We do not support Windows, so please use VirtualBox or Vagrant instead with Ubuntu or Linux Mint.
It's simple; there is no CLI, and you don't need to install anything with NPM. You just use git!
You have two choices for installation:
git clone your fork locally).We make configuration easy through a file called .env file using dotenv.
However, you'll need to modify it slightly for your own. Let's dive into how it works!
Configuration is managed by the following:
src/config/index.js (reads in process.env.SOME_VAR)src/config/environments/ (sets defaults per environment, e.g. you can pass NODE_ENV=staging and it will load the file at /src/config/environments/staging.js)Precedence is taken by the environment configuration files, environment variables, then the .env file.
Basically dotenv won't set an environment variable if it already detects it was passed as an environment variable.
Take a look in the src/config folder contents and also at the default .env.example file.
We've provided a default file called .env.example, which you will need to rename to .env and customize yourself.
In order to set-up defaults needed for Glazed app to boot, please follow these instructions:
.env.example to .envhttp://yourdomain.com (replace with your domain) and also http://localhost:3000 (for local development)http://yourdomain.com/login/ok (again, replace with your domain) and also http://localhost:3000/login/ok (again, for local development).env file (example below)-GOOGLE_CLIENT_ID=
+GOOGLE_CLIENT_ID=424623312719-73vn8vb4tmh8nht96q7vdbn3mc9pd63a.apps.googleusercontent.com
-GOOGLE_CLIENT_SECRET=
+GOOGLE_CLIENT_SECRET=Oys6WrHleTOksqXTbEY_yi07
.env file (example below)-AWS_IAM_KEY=
+AWS_IAM_KEY=AKIAJMH22P6W674YFC7Q
-AWS_IAM_SECRET=
+AWS_IAM_SECRET=9MpR1FOXwPEtPlrlU5WbHjnz2KDcKWSUcB+C5CpS
.env (example below)-AWS_S3_BUCKET=
+AWS_S3_BUCKET=glazed-development
.env file (example below)-AWS_CF_DI=
+AWS_CF_DI=E2IBEULE9QOPVE
-AWS_CF_DOMAIN=
+AWS_CF_DOMAIN=d36aditw73gdrz.cloudfront.net
src/assets/browserconfig.xml and src/assets/manifest.json files.That's it!
You should have Glazed installed and configured by now.
cd /path/to/glazed/
npm install
npm run watch
The watch script will automatically open a browser tab for you (with LiveReload enabled!).
We've written a comprehensive tutorial for deployment, continuous integration, and how to automate everything – you can read the article here.
If you're just interested in what tools/services we recommend, then here is a brief list:
1 Baked into Glazed by default – you just need to provide credentials in the configuration step
2 You can get $10 free credit for signing up by clicking our referral link above
3 We include SIGTERM listener for graceful reloading, see src/index.js for more insight
4 You can send 150,000 free credits transactional emails if you're bootstrapped and DMARC compliant
5 You can get $100 free credit for signing up by clicking our referral link above
The only way to ship code faster is to respect these three points:
Here is a brief list of recommended tools used to ship rapidly developed MVP's:
.github folder of GitHub contribution templates (e.g. ./github/PULL_REQUEST_TEMPLATE.md is a pull request template).google-chrome, git-extras, redis, mongodb, vim, wget, ...).vim as your editor to write your code – build up muscle memory by installing magnitude of plugins, which will automate your puny human mistakes. If you need inspiration, here is @niftylettuce's vim config.eslint plugin into your text editor so that on file save it lints your code according to the rules defined in the .eslintrc file.package.json file tidy by running fixpack after you alter it.npm install --save <name> to install packages, use pnpm to install them faster; pnpm install --save <name>.Yes, there is a book (coming soon) called Rapid MVP's. It comes with Markdown, HTML, and PDF versions, and also accompanying source code AND screencasts! The author @niftylettuce is self-publishing, and goes in-depth to show you how to build rapid MVP's. The book will include a "How It's Made" for at least two of his new (and hopefully profitable) side-projects.
It is available for early bird pre-order right now at https://rapidmvp.com! Even if you don't buy the book, you can still get free/inspirational behind the scenes tips, tutorials, and videos! And a sticker!
Get a FREE GLAZED STICKER mailed to you: https://rapidmvp.com (no pre-order required)
Join us in Slack. Still need help? File an issue.
We provide updates to this repository and a detailed changelog, which you can then add/merge into your project. You will need to "star" and "watch" this repository to stay active. We don't have an automated update system or a Google Group (and do not plan to). It is your duty as a Rapid MVP developer to stay updated. Lastly, it's a necessity that you join us on Slack to stay in the loop!
You can also follow us on Twitter here:
Glazed v1.0.0 was released in May 2016 by @niftylettuce.
It is a modernized derivative of his project "Eskimo" (a derivative of "Expressling").
Of course! Please email Niftylettuce LLC at niftylettuce@gmail.com to get in touch with a developer team fit for your project. Even if we can't find someone for you, we'd love to help put you in the right direction. We recommend to join us in Slack first!
FAQs
Glazed is an opinionated yet simple framework
We found that glazed demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.