{"id":20645505,"url":"https://github.com/pedrohenriques/nodejs_backend_boilerplate","last_synced_at":"2026-04-10T00:04:43.393Z","repository":{"id":91937454,"uuid":"158252545","full_name":"PedroHenriques/NodeJS_Backend_Boilerplate","owner":"PedroHenriques","description":"Boilerplate for a services based backend application in NodeJS.","archived":false,"fork":false,"pushed_at":"2018-12-21T17:19:58.000Z","size":279,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-17T09:33:50.153Z","etag":null,"topics":["backend","boilerplate","docker","expressjs","mongodb","nodejs","rabbitmq","redis","socket-io"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PedroHenriques.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2018-11-19T16:00:38.000Z","updated_at":"2018-12-21T17:17:26.000Z","dependencies_parsed_at":null,"dependency_job_id":"81b508f2-cdcb-42fa-bcb6-890ea00aee8e","html_url":"https://github.com/PedroHenriques/NodeJS_Backend_Boilerplate","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PedroHenriques%2FNodeJS_Backend_Boilerplate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PedroHenriques%2FNodeJS_Backend_Boilerplate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PedroHenriques%2FNodeJS_Backend_Boilerplate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PedroHenriques%2FNodeJS_Backend_Boilerplate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PedroHenriques","download_url":"https://codeload.github.com/PedroHenriques/NodeJS_Backend_Boilerplate/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":242714052,"owners_count":20173581,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["backend","boilerplate","docker","expressjs","mongodb","nodejs","rabbitmq","redis","socket-io"],"created_at":"2024-11-16T16:20:10.000Z","updated_at":"2025-10-29T05:34:10.271Z","avatar_url":"https://github.com/PedroHenriques.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![Build Status](https://travis-ci.org/PedroHenriques/NodeJS_Backend_Boilerplate.svg?branch=master)](https://travis-ci.org/PedroHenriques/NodeJS_Backend_Boilerplate)\n\n# Boilerplate for a services based backend application in NodeJS\n\n## The core technologies used are:\n\n- **NodeJS** (v11.*)\n- **Redis** (v4.*)\n- **MongoDB** (v4.*)\n- **RabbitMQ** (v3.*)\n\n## In development environment these tools are also available:\n\n- **Redis Commander**: A GUI for Redis\n- **Mongo Express**: A GUI for MongoDB\n- **RabbitMQ Management**: A GUI for RabbitMQ\n- **Mailhog**: A mail catcher tool\n\n# Setup\n\n## Production mode\n\nA `docker-compose` file is available with this repo, but you'll need to adjust it to your production needs and architecture.  \nThe following files require production environment adjustments:\n- `webserver/middleware/validateCORS.ts`: If needed, add the domains you want to allow to make requests to the application, for CORS purposes.\n\n## Development mode\n\n1. Open a console/terminal and `cd` into the repo's root directory\n2. Run the command `npm i`\n3. Run the command `npm run watch`\n4. Open a new console/terminal in the `docker` directory\n5. Run the command `docker-compose -f ./docker-compose.dev.yml up`\n\n**NOTES**\n\n. A GUI for the **emails sent** is available at `http://localhost:8025`  \n. A GUI for **Redis** is available at `http://localhost:8081`  \n. A GUI for **MongoDB** is available at `http://localhost:8082`  \n. A GUI for **RabbitMQ** is available at `http://localhost:8083`\n\n# Configuration\n\n## Environment Variables\n\nAll environment variables are defined in the `docker-compose` files and the associated `.env` file.  \nThese files are located in the `docker/` directory.\n\n## Redis\n\nThe container with the redis image will receive one of the configuration files located in the `redis/` directory.  \n\nThe `docker-compose.yml` file will use the `redis/redis.conf` file and the `docker-compose.dev.yml` file will use the `redis/redis.dev.conf` file.\n\n## MongoDB\n\nThe files in the `mongodb/scripts/` directory will be mounted into the `/docker-entrypoint-initdb.d/` directory inside the container.  \n\nMongoDB will automatically execute any `.sh` or `.js` files located inside that directory, in alphabetical order.  \nMore information can be found in the [official mongoDB docker image github](https://github.com/docker-library/docs/blob/master/mongo/README.md#initializing-a-fresh-instance).\n\n## RabbitMQ\n\nThe files in the `rabbitmq` directory will be mounted into the container with the RabbitMQ image.  \nPlace any configuration files inside the `dev` or `prod` directories.  \n\nThis boilerplate is using the `rabbitmq:*-management-alpine` variant of the RabbitMQ docker image, which comes with the management plugin activate.  \nThe `definitions.json`, supported by the management plugin, allows you to configure the initial setup of your message queue.  \nUse it to configure any `users`, and their `permissions`, `vhosts` and `queues` that should be created at bootup.\n\n## Application Configurations\n\nThis boilerplates comes with a service that will load files into the cache.  \n\nYou are encouraged to load any configuration files needed by the application code into the cache and then access it through the `cache` service when needed.  \n\nFurther information about the `configLoader` service is available in the `documentation/services/configLoader.md` file.\n\n# Test Client Application\n\nA test client application is available, in the `webserver/client_app.js` file, which allows an easy way to interact with the API. You can run this client via NodeJS environment.\n\nHere is an example use, running in the `NodeJS CLI` from the project root directory:\n\n```js\nconst client = require('./webserver/client_app');\n\n// this will create a user pending activation and send an activation email\nclient.createUser('test@test.com', 'my password');\n\n// this will activate the account and create the user entity with an ID\nclient.activateUser('test@test.com', 'the token in the email link');\n\n// this will log you in\nclient.login('test@test.com', 'my password');\n\n// now you can call any API end point that requires being logged in\n\n// this will log you out\nclient.logout();\n\n// this will start the lost password process and send an email with a link to reset the password\nclient.lostPassword('test@test.com');\n\n// this will allow you to reset your account password\nclient.resetPassword('test@test.com', 'the token in the email link', 'new password');\n\n// login with the new password\nclient.login('test@test.com', 'new password');\n```\n\n# Services\n\nThe application is built in several services, each in a docker container.  \nThis makes it easier to scale bottleneck services, by creating replicas of those services and also makes the application modular and thus easier to maintain and modify over time.  \n\nThe various services communicate via `events` with each other that trigger actions in other containers.  \nThese events are dispatched through `sockets` and/or `message queues`.  \n\nThe socket connections support 2 way communication if needed, while the message queue is great for \"fire and forget\" events.  \n\nDetailed information about each service is available in the `documentation/services/` directory.\n\n# Events\n\nAs mentioned above, each service is in a dedicated docker container and communication between containers is done by dispatching events.  \n\nThese events can be sent over a `socket` or through a `message queue`.  \n\n**Sockets** allow direct two way communication between services, which permit a callback function to be provided with the event.  \nThis is the recommended way to handle events that expect something in return.  \n\n**Queue messages** allow for a durable event dispatching, where if the event fails to be processed it can be requeued and tryied again.  \nThey are not, however, ideal at handling events that expect a callback.  \n\nThe event dispatchers provided with this boilerplate make it possible to provide the same payload, in your code, for socket and message queue.  \nThey will make the necessary adjustments for the different systems.  \n\nThis also means that the handlers, in each service, that will be called on an event, should be the same regardless of how the event was dispatched (i.e. socket or messahe queue).  \n\nThis boilerplate uses the message queue for email related events and some cache and db events, that don't require any information as a callback.  \nSockets are used for cache and db 'search' events, since the dispatching code is expecting data in return.  \n\nHowever, you can easily change this behavior by switching the socket event dispatchers with the message queue event dispatchers.\n\n## Event Dispatchers\n\nThis boilerplate provides event dispatchers for use with sockets and the message queue.  \n\nThey are located in the `sharedLibs/utils/eventDispatchers.ts` module, and are used in all specific event dispatchers used by the **cache**, **db** and **mailer** related events.\n\n# Socket Events\n\n## Creating a socket server\n\nTo facilitate and standardize creating socket servers, a factory function is available in the `sharedLibs/utils/socketServer.ts` file.  \n\nThis function has the following signature:  \n\n```ts\n(handler: (socket: socketIo.Socket) =\u003e void, port: number, options?: socketIo.ServerOptions) =\u003e socketIo.Server\n```\n\nwhere\n\n- **handler**: A function used to create your event bindings\n\n- **port**: The port the socket server will use.\n\n- **options**: The options object, defined by the Socket.IO package, to use for this server.\n\n## Creating a socket connection\n\nTo facilitate creating socket connections and manage multiple connections, the module located in the `sharedLibs/utils/socketConnection.ts` file exposes several helper functions that can create a socket connection to another service and assign them to tags.  \n\nThese tags make it easier to later get a reference to a specific socket and dispatch events to the target service.  \nThe valid tags are defined in the `TSocketTags` type, in the `sharedLibs/types/events.ts` file.\n\n## Socket Event Callbacks\n\nSome events will accept a callback with the signature:\n\n```ts\n(error: Error | null, value?: any) =\u003e void\n```\n\nIt will ba called by the event handler after all processing has ended.  \n\nIn case of a success, the callback will receive `null` as the first argument and `some value` as the second argument, which will depend on the specific event.  \n\nIn case of a failure, the callback will receive an instance of `Error` as the first argument and nothing as the second argument.\n\n# Message Queue Events\n\nThe `sharedLibs/utils/queue.ts` module provide functions that will facilitate interactions with the message queue system (MQ).  \n\nThe easiest way to setup a connection to the message queue is to call the `connectWithRetry()` function.  \nThis function will keep trying to connect to the MQ, waiting 1 second between tries.  \n\nThe RabbitMQ container will likelly take longer to setup up than the containers that will connect to it, which means its is expected that the connection will fail a few times before succeeding.\n\n# API Endpoints\n\nDetailed documentation of the available API endpoints can be found in the `documentation/api/` directory.\n\n# Functionality Overview\n\nThis boilerplate is ment to be a basis for building applications and not a full featured application, thus it has minimal out of the box features.  \n\nIt does come with a user account management system, which is detailed below.  \n\n**NOTE:** all configurations for this system are located in the `config/userAccountConfig.json` file.\n\n## User Account Registration\n\nWhen a user registers an account, the user's information will be temporarily stored in the cache, until the user activates the account, via the email sent to the address provided as part of the registration data.  \n\nAn activation token will be generated and associated with the user's data.  \nThis token will be stored in the cache and set to automatically expire after **24 hours**.  \n\nThe amount of seconds the activation token will be valid is defined in the `accountRegistration.tokenDurationInSeconds` property of the config file.  \n\n**NOTE:** the user's password is hashed before being stored in the cache.\n\n## User Account Activation\n\nAfter an account is registered, an activation email is sent to the user with an URL.  \nThis URL is built based on the `domain.*RootUrl` and `accountRegistration.activationRelUrl` properties of the config file.  \n\nWhen a request is made to the relevant API endpoint with an email-token pair, the data associated with that token will be removed from the cache and an entry will be inserted into the DB, where an **ID** will be assigned to this user.  \n\nOn a successfull activation, a confirmation email will be sent to the user, with a URL to the login page.  \nThis URL is built based on the `domain.*RootUrl` and `accountActivation.loginRelUrl` properties of the config file.\n\n## User Login\n\nWhen a request is made to the relevant API endpoint with an email-password pair, a **session** will be created to facilitate authentication in future requests.  \n\nThe session will be stored in the **cache**, and set to automatically expire after **6 hours**.  \nThe amount of seconds the session will remain active is defined in the `login.sessionDurationInSeconds` property of the config file.  \n\nThe response sent to the login HTTP request will contain a **cookie** with the session ID, which should be sent in all future requests.  \nThe name of the cookie is defined in the `login.cookieName` property of the config file.\n\n## Session Handling\n\nThe `session` expressJS middleware, located in the `webServer/middleware/session.ts` file, will check if a session ID was sent with the request.  \n\nIf a session ID was sent, then a check will be made to see if the user's data was changed since that session was created.  \nIf any of the user's data was changed since then, the session will be terminated, requiring the user to login again.\n\n## User Account Password Recovery\n\nWhen a request is made to the relevant API endpoint with an email address, a password reset token will be generated and stored in the cache, set to automatically expire after **1 hour**.  \nThe amount of seconds the token will remain valid is defined in the `lostPassword.tokenDurationInSeconds` property of the config file.  \n\nAn email will be sent to that address with a URL to the page where the user can insert the new password.  \nThis URL is built based on the `domain.*RootUrl` and `lostPassword.pwResetRelUrl` properties of the config file.  \n\n**NOTE:** if all the code runs, the response to the HTTP request will always have a status code of `200` whether an activated user account exists for the provided email address or not.\n\n## User Account Password Reset\n\nWhen a request is made to the relevant API endpoint, the new password will be hashed and the associated user data in the DB will be updated.  \n\nOn a successfull update, a confirmation email will be sent to the user.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpedrohenriques%2Fnodejs_backend_boilerplate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpedrohenriques%2Fnodejs_backend_boilerplate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpedrohenriques%2Fnodejs_backend_boilerplate/lists"}