Zero Waste Locator
What this App is about
I try to live a Zero Waste lifestyle. In brief, Zero Waste for me is about reducing consumption, in particular plastic products. I moved to Oslo in Norway, I realized it takes time to learn where plastic-free products are sold.
For this reason I am implementing this app where users can search and log stores selling Zero Waste or Less Waste products. This app uses Google Maps to search for stores, and will allow you to save them together with their products so that you or other users can look them up.
On the back-end a server is based on Node.js/Express server. The Mongoose ODM is used to connect Node.js and the MongoDB database. It provides a schema based solution to organize models and running CRUD operations. JSON web tokens [JWT] handle user authentication and identity management. The front-end is built with Angular-CLI 7, Bootstrap, and Angular Bootstrap. Of course, the app uses RxJS for asynchronous or callback-based code.
Through the frontend users can search an address using Google Maps' geolocation. The results are displayed as markers on the Google map.
I implemented a "caching" system that checks whether the searched address is already present in the MongoDB database [DB]. This allows the app to call Google Maps less often, and to load a store/location already present in the DB.
The user has a personal quota for the number of geolocation searches they can run. The quota can be set in three environment variables (see below) as an integer for the maximum number of queries per hour, day, and total maximum. This was done to limit my bill with the Google Maps API.
A form appears when you click on a marker. This form contains user editable information on the store such as the store type, store description, etc. This form allows the user to save or update the store/location to the DB.
To use the Google Map functionality a user is required to register and login. JWT is used to transmit sensitive information (e.g. passwords, access tokens) between front-end and back-end. A password reset functionality is implemented in the back-end using express-nodemailer, handlebars for express and express-nodemailer, and AJAX requests.
NB: This app does not use agm-core for Google Maps as described in many tutorials. IMO documentation is insufficient to extend the agm-core component and implement functionalities such as InfoWindow or callbacks from markers.
node, npm, mongoDB, Angular
Install node, npm, mongoDB, Angular CLI, and see the standard generated README below. Install the Angular and Node.js dependencies with:
cd backend npm run client-install
This script uses concurrently to run
npm install on both back- and front-end folders.
Create a .env file with environment variables for the Node.js back-end. Use a template in .env_example.
cp .env_example .env vi .env
Similarly to dotenv, set up environment variables for the Angular frontend in the ./environment.ts and ./environment.prod.ts files, which are used for development and production, respectively.
Get a Google Maps API key here to use Google's geolocation service. Place the API key in the ./src/index_INSERTKEY.html file, then rename that file to index.html. This allows you to use it for geocoding from the front end (see src/app/modules/map/map.component.ts).
The code still includes my implementation of geocoding from the server back-end. This implementation uses npm-geocoder but I commented it out in the code. To use it set up a Google Maps API key for using it on a server and see the backend/server.js file.
Launching the app
Launch the MongoDB database:
mongod --dbpath <path to data directory>
Launch the Node.js back-end in the ./backend directory. As an example, use one of these three commands below:
cd backend npm start //using npm node server.js //using node nodemon //using nodemon
Before launching Angular fix the index.html file as explained before:
cp ./src/index_INSERTKEY.html ./src/index.html
Launch Angular for the frontend with one of these two commands:
ng serve npm run start
Alternatively, use this command to automate the previous two commands on the back- and front-end:
cd backend npm run dev
Prepare for production
In addition to the previous steps compile the Angular app into the /dist folder:
ng build --prod
The /dist folder is served by Node.js when the environment variable NODE_ENV is set to 'production', so do that before launching the backend with e.g.:
NODE_ENV=production node server.js
How it looks like
Here are some references I am using to develop MEAN applications:
This project was generated with Angular CLI version 7.0.3.
ng serve for a dev server. Navigate to
http://localhost:4200/. The app will automatically reload if you change any of the source files.
ng generate component component-name to generate a new component. You can also use
ng generate directive|pipe|service|class|guard|interface|enum|module.
ng build to build the project. The build artifacts will be stored in the
dist/ directory. Use the
--prod flag for a production build.
Running unit tests
ng test to execute the unit tests via Karma.
Running end-to-end tests
ng e2e to execute the end-to-end tests via Protractor.
To get more help on the Angular CLI use
ng help or go check out the Angular CLI README.