This is an Express.js based Nodejs server that implements production-ready error handling and logging following latest best practices.
This project is inspired by an idea to quickly create a production ready project with all the required infrastructure at low cost yet with important security measures in place and ability to quickly scale in order to ship a quality product to early adopters. Ideal for quickly starting an app to validate ideas and scale if needed.
One of the main points is that we do not need to deal with setting up servers or databases to validate an idea. Therefore, this opensource project relies on cloud solutions for managing DBs, deployments, sending transactional emails, which have free plans with useful and secure features. And you can always switch to a paid plan if your projects grow fast and you need more power.
Current stack is JavaScript/Nodejs, MongoDB, Redis, Graphql. Now for deployment.
- Nodejs
v. 10.\*
- Error handling
v1.0.0
- Logging with Morgan and Winston
- Application Configuration with node-config
- Linting
- Testing with Jets and Supertest
- MongodDb support with Mongoose
v1.1.0
- Redis support
v1.2.0
- Settings to push images to docker hub (optional)
- Sentry error tracking
- GraphQl integration with apollo-server-express and Prisma
- Authentication with email/password
createUser
andlogin
mutations with auth check - Subscriptions to
userCreated
anduserUpdated
mutations (can be easily extended for any other mutation type) - Priority job queue with Kue (e.g: for sending transactional emails). Queue implementation can be easily replaced with anything you prefer (apart from Kue). Emails (transactional) are sent with mailjet that offers 200 emails/day for free under the Free plan.
- Follows best practices from The largest Node.JS best practices list
- Structure your solution by components
- Separate Express 'app' and 'server'
- Use environment aware, secure and hierarchical config
- Use Async-Await or promises for async error handling
- Use only the built-in Error object (decorated with Boom)
- Distinguish operational vs programmer errors
- Handle errors centrally, not within an Express middleware
- Shut the process gracefully when a stranger comes to town
- Use a mature logger to increase error visibility
- Use ESLint
- Detect code issues with a linter
- Embrace linter security rules
- Node.js Specific Plugins
- Start a Codeblock's Curly Braces on the Same Line
- Don't Forget the Semicolon
- Prefer const over let. Ditch the var
- Requires come first, and not inside functions
- Do Require on the folders, not directly on the files
- Use the === operator
This project uses Git hook to validate commit messages based on community standards
I am always open to your feedback
- Authentication (Gmail, Facebook, LinkedIn, Twitter)
- Password recovery
- add/remove social accounts
- Backend (RBAC, user management)
- Logic to separate free/paid services
- Basic CSS with something simple like tailwindcss
- GDPR ready (cookies, settings)
- TypeScript (maybe)
- Scaffolding tool to choose from the mentioned FWs/Libs, etc.
- Set up environment variables
- Install and start Docker
- Install npm dependencies
- Create account and connect to MongoDB Atlas cloud instance using the FREE plan
- Set up Prisma
- Create account and connect to RedisLabs cloud instance using the FREE plan
- Create account and setup Sentry error tracking
- Create account and setup MailJet to send transactional emails
- Kue UI dashboard
- Run server
- Making changes to Graphql schemas
- Test error handling
Rename *.sample.js
files in /server/config
directory:
default.sample.js -> default.js
production.sample.js -> production.js
test.sample.js -> test.js
Create .env
file in the root of the project with the following lines:
//.env
MONGO_DB=mongodb+srv://<user>:<password>@cluster0-clxgl.mongodb.net/test?retryWrites=true&w=majority
PRISMA_URL=http://localhost:4466
NGINX_PORT=3045 // or whatever you want
More details on how config works see node-config. You may also find Securing production config files useful
- Install Docker (if not yet installed) and make sure it runs
- Run
docker-compose up
- Run
npm install
- Create an account with MongoDB Atlas using the FREE plan and follow instructions here
- Prisma serves as an ORM. Run
npm i -g prisma
to install it - Schema is defined here
./prisma/datamodel.prisma
- Run
prisma deploy
or(npm run deploy)
- Later, during development, use
npm run get-schema
to download schema from endpoint to./src/generated/prisma.graphql
. Note that it will run automatically onprisma deploy
or(npm run deploy)
as it is set up inpost-deploy
hook in/prisma/prisma.yml
- Prisma GraphQl playground is available here
http://localhost:4466
- Apollo server GraphQl playground -
http://localhost:${NGINX_PORT}/graphql
- Create an account with Redislabs using the FREE plan (choose Cloud Hosted - free up to 30MB) and follow instructions here
!!!Note!!! the redis url looks as follows (the part after @
is the Endpoint from the dashboard configuration tab):
redis://:<password>@redis-<...>.cloud.redislabs.com:<port>
- Create a Sentry account here
- Add
your-sentry-dsn
to all configuration files in/config
dir
sentry: {
dsn: 'your-sentry-dsn',
},
- Create a MailJet account here
- Add
your-mailjet-api-key
andyour-mailjet-secret
to all configuration files in/config
dir
mailjet: {
api_key: 'your-mailjet-api-key',
secret: 'your-mailjet-secret',
},
- Important!!! You need to use a domain-based email address as an email sender (e.g. your project's domain name) to ensure emails are delivered to the inbox. Otherwise, they will end up in spam (including example@gmail.com once). In your MailJet account you can verify your email and take additional measures (e.g.SPF and DKIM settings) to ensure your emails are delivered.
- The dashboard is available under
http://localhost:3050/active
or via nginxhttp://localhost:${NGINX_PORT}/kue/active
npm run dev
- development mode ornpm run start
- production modedocker-compose -f docker-compose.yml -f test-env.yml up
- run server in test environment
npm run test:unit
- run unit testsnpm run test:int
- run integration testsnpm run coverage
- test coveragenpm run lint
- lint
- update/add data model
/prisma/datamodel.prisma
- update/add schema
/src/graphql/schema.graphql
- update/add queries, mutations or subscriptions
/src/graphql/resolvers/
- run
npm run deploy
to update prisma data model and generate schema in/generated
-
navigate to
/api/crash/
and click on any of the listed optionsNote, that crash routes for testing error handling are not available in
production
env
- Add your secret in
prisma/prisma.yml
secret: putYourSuperSecretTextHere
- Add the same secret in
src/db/prisma.js
secret: 'putYourSuperSecretTextHere',
- run
npm run deploy
Now the http://localhost:${NGINX_PORT}/graphql
endpoint will work as expected.
However the http://localhost:4466
will return "Your token is invalid"
error. To be able to use it, you need to generate an authorization token and use it in HTTP headers. Here is how you do it:
- run
npm run get-prisma-token
- copy the generated token
- insert the following HTTP headers (bottom left corner) in graphql playground under
http://localhost:4466
{
"Authorization":"Bearer 'generated token'" // mind the space between "Bearer" and the token
}
To push images to Docker Hub you need to provide your Docker user name and password as environment variables. Refer to Travis documentation for more details
Once environment variables set, uncomment related lines in .travis.yml
file