🚚 A boilerplate for Node.js, Express, Mongoose, Heroku, mLab, Nodemon, PM2, and Babel.
This seed repository provides the following features:
- ---------- Essentials ----------
- API routing with Express.
- Data query language with GraphQL.
- Object document mapping with Mongoose.
- Object relational mapping with Sequelize.
- Utility functions with Lodash.
- Reactive extensions with ReactiveX.
- Authenticate requests with Passport.
- Real-time bidirectional communication with Socket.
- In-memory data structure store with Redis.
- Machine learning with TensorFlow.
- ---------- Tools ----------
- Next generation JavaScript with Babel.
- JavaScript static code analyzer with ESLint.
- Type annotations with Flow.
- Testing platform with Jest.
- HTTP testing with Supertest.
- Test coverage integration with Codecov.
- Automatically restart application with Nodemon.
- Keeping application alive with PM2.
- ---------- Environments ----------
- Server-side platform with Node.
- Version control with Git.
- Code repository with GitHub.
- Fast and deterministic builds with Yarn.
- Cloud application hosting with Heroku.
- Cloud NoSQL database hosting with mLab.
- Cloud SQL database hosting with ElephantSQL.
- Cloud Storage hosting with Cloudinary.
- Cloud memory cache hosting with RedisLabs.
- Monitoring service with UptimeRobot.
- Log management service with Papertrail.
- Performance and security with Cloudflare.
- Software container with Docker.
- Continuous integration with CircleCI.
Here are some related seed repositories:
- ---------- Client-side ----------
- Web Starter Kit - Make for Progressive Web Apps.
- Mobile Starter Kit - Make for Cross-platform Mobile Apps.
- Desktop Starter Kit - Make for Cross-platform Desktop Apps.
- ---------- Server-side ----------
- Platform Starter Kit - Make for Flexible Cloud Platform.
- Functions Starter Kit - Make for Serverless Cloud Functions.
- Infrastructure Starter Kit - Make for Containerized Cloud Infrastructure.
- Clone this Boilerplate
$ git clone --depth 1 https://github.com/Shyam-Chen/Backend-Starter-Kit.git <PROJECT_NAME>
$ cd <PROJECT_NAME>
- Install Dependencies
$ yarn install && yarn typed
- Run the Application
$ yarn start
- Test the Application
$ yarn test
- Build the Application
$ yarn build
- Build and run the container in the background
$ docker-compose up -d api
- Run a command in a running container
$ docker-compose exec api <COMMAND>
- Remove the old container before creating the new one
$ docker-compose rm -fs
- Restart up the container in the background
$ docker-compose up -d --build api
- Push images to Docker Cloud
# .gitignore
.DS_Store
node_modules
npm
dist
coverage
+ Dockerfile.dev
+ Dockerfile.prod
*.log
$ docker login
$ docker build -f Dockerfile.<dev|prod> -t <IMAGE_NAME>:<IMAGE_TAG> .
# checkout
$ docker images
$ docker tag <IMAGE_NAME>:<IMAGE_TAG> <DOCKER_ID_USER>/<IMAGE_NAME>:<IMAGE_TAG>
$ docker push <DOCKER_ID_USER>/<IMAGE_NAME>:<IMAGE_TAG>
# remove
$ docker rmi <REPOSITORY>:<TAG>
# or
$ docker rmi <IMAGE_ID>
- Pull images from Docker Cloud
# circle.yml
+ echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_USERNAME" --password-stdin
docker login -u="<DOCKER_USERNAME>" -p="${HEROKU_TOKEN}" registry.heroku.com
- docker build -f Dockerfile.prod -t registry.heroku.com/<HEROKU_PROJECT>/web .
+ docker pull <DOCKER_ID_USER>/<IMAGE_NAME>:<IMAGE_TAG>
docker push registry.heroku.com/<HEROKU_PROJECT>/web
Set your local environment variables.
// src/env.js
export const SECRET = process.env.SECRET || <PUT_YOUR_SECRET_HERE>;
export const MONGODB_URI = process.env.MONGODB_URI || <PUT_YOUR_MONGODB_URI_HERE>;
export const POSTGRES_URL = process.env.POSTGRES_URL || <PUT_YOUR_POSTGRES_URL_HERE>;
export const REDIS_PORT = process.env.REDIS_PORT || <PUT_YOUR_REDIS_PORT_HERE>;
export const REDIS_HOST = process.env.REDIS_HOST || <PUT_YOUR_REDIS_HOST_HERE>;
export const SENTRY_DSN = process.env.SENTRY_DSN || <PUT_YOUR_SENTRY_DSN_HERE>;
Set your deployment environment variables.
# Dockerfile.<dev|prod>
ENV SECRET <PUT_YOUR_SECRET_HERE>
ENV MONGODB_URI <PUT_YOUR_MONGODB_URI>
ENV POSTGRES_URL <PUT_YOUR_POSTGRES_URL_HERE>
ENV REDIS_PORT <PUT_YOUR_REDIS_PORT_HERE>
ENV REDIS_HOST <PUT_YOUR_REDIS_HOST_HERE>
ENV SENTRY_DSN <PUT_YOUR_SENTRY_DSN_HERE>
- Example of REST
import { Router } from 'express';
import { List } from '~/document';
const router = Router();
router.get('/', async (req, res, next) => {
try {
const data = await List.find({}).exec();
res.json(data);
} catch (err) {
next(err);
}
});
export default router;
- Example of GraphQL
import gql from 'graphql-tag';
import { List } from '~/document';
export const listTypeDefs = gql`
type List {
_id: ID!
text: String!
}
type Query {
list: [List]
}
`;
export const listResolvers = {
Query: {
async list(root, { text }) {
try {
const data = await List.find({}).exec();
return data;
} catch (err) {
console.error(err);
}
}
}
};
- Example of Document
import mongoose, { Schema } from 'mongoose';
const listSchema = Schema({
text: String,
});
export const List = mongoose.model('List', listSchema);
- Example of Relational
export default (sequelize, DataTypes) => {
const List = sequelize.define('List', {
text: DataTypes.STRING
});
return List;
};
- Example of Lodash
import { of } from 'rxjs';
import { lowerFirst, pad } from 'lodash';
of(lowerFirst('Hello'), pad('World', 5))
.subscribe(value => console.log(value));
// hello
// World
- Example of ReactiveX
import { timer, of } from 'rxjs';
import { mapTo, combineAll } from 'rxjs/operators';
timer(2000)
.pipe(
mapTo(of('Hello', 'World')),
combineAll(),
)
.subscribe(value => console.log(value));
// ["Hello"]
// ["World"]
- Example of Socket
import { io } from '~/core/socket';
io.emit('A', { foo: 'bar' });
io.on('B', data => console.log(data)); // { foo: 'baz' }
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.0.1/socket.io.js"></script>
<script>
const socket = io();
socket.on('connect', () => console.log('WS: Accept a connection.'));
socket.on('A', data => {
console.log(data); // { foo: 'bar' }
socket.emit('B', { foo: 'baz' });
});
</script>
- Example of Redis
import { client } from '~/core/redis';
client.hmset('thing', {
foo: 'js',
bar: 'html',
baz: 'css'
});
client.hgetall('thing', (err, object) => {
console.log(object);
});
.
├── src
│ ├── core -> core feature module
│ ├── document -> mongodb models
│ ├── graphql -> query language
│ ├── relational -> postgresql models
│ ├── rest -> restful api
│ ├── shared -> shared feature module
│ ├── api.js
│ └── env.js
├── tools
│ └── ...
├── .babelrc
├── .editorconfig
├── .eslintrc
├── .flowconfig
├── .gitignore
├── Dockerfile
├── LICENSE
├── README.md
├── circle.yml
├── docker-compose.yml
├── jest.config.js
├── package.json
├── processes.js
└── yarn.lock