{"id":15170756,"url":"https://github.com/gitericsson/natours","last_synced_at":"2026-02-21T10:02:53.871Z","repository":{"id":232444031,"uuid":"784369060","full_name":"gitEricsson/Natours","owner":"gitEricsson","description":"Natours is a real-world RESTful API and server-side rendering WebApp for booking Tours.","archived":false,"fork":false,"pushed_at":"2024-05-23T10:11:54.000Z","size":99685,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2024-10-30T02:28:20.252Z","etag":null,"topics":["agnostic","brevo-api","css3","express","flutterwave-api","fullstack","javascript","jwt","leaflet-api","mongodb-atlas","mongoose","mvc-architecture","natours","oauth2","pug","server-side-rendering"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/gitEricsson.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":null,"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":"2024-04-09T17:59:46.000Z","updated_at":"2024-07-24T11:57:09.000Z","dependencies_parsed_at":null,"dependency_job_id":"df9c4b81-9a1e-4cf9-8d84-07218cd359cc","html_url":"https://github.com/gitEricsson/Natours","commit_stats":null,"previous_names":["gitericsson/natours"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gitEricsson%2FNatours","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gitEricsson%2FNatours/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gitEricsson%2FNatours/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/gitEricsson%2FNatours/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/gitEricsson","download_url":"https://codeload.github.com/gitEricsson/Natours/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243853681,"owners_count":20358461,"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":["agnostic","brevo-api","css3","express","flutterwave-api","fullstack","javascript","jwt","leaflet-api","mongodb-atlas","mongoose","mvc-architecture","natours","oauth2","pug","server-side-rendering"],"created_at":"2024-09-27T08:22:48.025Z","updated_at":"2025-10-19T06:04:12.666Z","avatar_url":"https://github.com/gitEricsson.png","language":"JavaScript","readme":"\u003c!-- PROJECT LOGO --\u003e\n\u003cbr /\u003e\n\u003cdiv align=\"center\"\u003e\n  \u003c!-- \u003ca href=\"https://ericsson-mapty.netlify.app/\"\u003e --\u003e\n    \u003cimg src=\"./public/img/logo-green-small.png\" alt=\"Logo\" height=\"75\"\u003e\n    \n  \u003c/a\u003e\n\n# Natours\n\n\u003c/div\u003e\n\n## Table of contents\n\n- [Overview](#overview)\n  - [About](#about)\n  - [The Challenge](#the-challenge)\n  - [Features](#features)\n  - [Updates](#updates)\n  - [Links](#links)\n- [My process](#my-process)\n  - [Keys](#keys)\n  - [Built with](#built-with)\n- [Author](#author)\n- [Acknowledgments](#acknowledgments)\n\n## Overview\n\n### About\n\nNatours is a real-world RESTful API alongside a server-side rendering WebApp for booking Tours.\n\n### The Challenge\n\nMy goal was to recreate [Jonas Schmedtmann's](https://github.com/jonasschmedtmann) Natours WebApp from scratch and make some updates to it.\n\nSome of the challenges I faced along the way were:\n\n- Integrating [Flutterwave](https://developer.flutterwave.com) in place of Stripe due to accessibility issues\n- Replacing [Leaflet](https://leafletjs.com/index.html) with Mapbox as the later is now a premium tool\n- Implementing [Brevo](https://developers.brevo.com) in place of Sendgrid due to SignUp problems encountered\n- Executing my project on [Render](https://render.com/) instead of Heroku as the free-to-deploy plan isn't available anymore\n- Bainstorming the UI design, Application Logic, and Business Logic for the updates\n\n### Features\n\n#### API - Backend\n\n- RESTful API- REST Architecture\n- CRUD(Create, Read, Update, Delete) operations on API\n- Creating, reading, updating, and deleting tours on the database\n- Creating, reading, updating, and deleting bookings on the database\n- Creating, reading, updating, and deleting reviews on the database\n- Creating, reading, updating, and deleting users on the database\n- 'Top 5 Cheap Tours', 'Monthly Plan', 'Tour Stats', 'Tours within Radius', and 'Distances to Tours from a Point' endpoints\n- 'Password Reset', 'Forgot Password', and 'Update Current User Password' endpoints\n- User Authentication with JWT\n- User Authorization and Permission: Admin, Lead-Guide, Guide, User (OAuth 2.0)\n- User input data validation\n- Password encryption with salt and hash (bcrypt)\n- Password reset token encryption (SHA 256)\n- User input data sanitization\n- Halt login requests using bcrypt\n- Rate-limiting implementation (express-rate-limit)\n- Special HTTP headers (helmet package)\n- Body payload limitation (in body-parser)\n- Evil regular expressions avoidance\n- JWT storage in HTTPOnly cookies\n- Mongoose for MongoDB (because of SchemaTypes)\n- Random password reset tokens with expiry dates\n- Access to JWT after password change denial\n- Proper error handling functionality\n- Global error handler Implementation\n- Parameter Pollution Prevention\n- Proper Data Modelling: Child, Parent, and Two-Way Referencing\n- Geospatial queries\n- Geospatial Aggregation\n- API documentation using [Postman](https://www.postman.com)\n- Mailing System using [Nodemailer](https://www.nodemailer.com) and [Mailtrap](https://mailtrap.io)(for development and testing)\n- Image uploads using [Multer](https://www.npmjs.com/package/multer)\n\n#### WebApp - Frontend\n\n- Error page rendering\n- Login Feature\n- Logout Feature\n- Reset Password Interface\n- Tour cards display\n- All Tours page\n- Individual Tour page: Review section, Map section, Tour details section, and Booking section\n- User settings\n- User Profile\n- Booked Tours page\n- Update user data page\n- Upload profile picture feature\n\n### Updates\n\n- Responsive Web Design across all Devices\n- Display or hide Mobile Menu Functionality\n- Cross-Site Request Forgery (csurf package) prevention\n- Re-authentication before a high-value action\n- Blacklist of untrusted JWTs Implementation\n- User Email Address Confirmation after Signup\n- Keep Users logged in with Refresh tokens using Interceptors\n- Two-factor Authentication per Login Implementation on both Front and Back ends\n- Automatic Focus and Navigation pin confirmation feature (UI and UX considerations)\n- Restriction that users can only review a tour that they have actually booked\n- Nested booking routes: /tours/:id/bookings and /users/:id/bookings\n- Improved tour dates: The Tour now includes 'participants' and a 'soldOut' field for each date in the DB, allowing users to select a date and check if the tour is still available before booking on both Front and Back ends\n- Booking Payment System using [Flutterwave](https://developer.flutterwave.com) in place of Stripe\n- Mailing Sytem using [Brevo](https://developers.brevo.com)(for production) instead of Sendgrid\n- Tour Location and Map Feature using [Leaflet](https://leafletjs.com/index.html) in lieu of Mapbox\n- Signup form Implementation\n- Checkout session for booking an appointment\n- Update no of participants after each booking confirmation\n\n### Links\n\n- Code URL: [Github Repo here](https://github.com/gitEricsson/Natours)\n- Live Site URL: [Live site here](https://natours-6ybv.onrender.com)\n\n## My process\n\n### Keys\n\nYou can use any of the keys below to make a card mock payment or get more from [Flutter's API documentation](https://developer.flutterwave.com/docs/integration-guides/testing-helpers/#cards)\n\n| Type                            | Card number         | CVV | PIN  | Expiry | OTP   |\n| :------------------------------ | :------------------ | :-- | :--- | :----- | :---- |\n| MasterCard PIN authentication   | 5531886652142950    | 564 | 3310 | 09/32  | 12345 |\n| Verve Card PIN authentication 2 | 5061460166976054667 | 564 | 3310 | 10/29  | -     |\n| Visa Card 3DS authentication    | 4187427415564246    | 828 | 3310 | 09/35  | 12345 |\n\n### Built with\n\n- Semantic HTML5 markup\n- CSS custom properties\n- Flexbox\n- CSS Grid\n- JavaScript\n- MVC Architecture\n- AJAX\n- API\n- NodeJS\n- REST Architecture\n- Express\n- Mongoose\n- MongoDB Atlas\n- Pug\n- JSON Web Token\n- ParcelJS\n- Flutterwave\n- Postman\n- Mailtrap\n- Brevo\n- Nodemailer\n- Leaflet\n- Axios\n- bcrypt\n- dotenv\n- got\n- Helmet\n- hpp\n- html-to-text\n- xss-clean\n- Slugify\n- Sharp\n- Morgan\n- Multer\n- express-rate-limit\n- Nodemon\n\n## Author\n\n- Website - [Ericsson Raphael](https://github.com/gitEricsson)\n- LinkedIn - [@ericsson](www.linkedin.com/in/ericssonraphael)\n- Gmail - [@ericsson](ericssonraphael@gmail.com)\n\n## Acknowledgments\n\n[Jonas Schmedtmann](https://github.com/jonasschmedtmann)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgitericsson%2Fnatours","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgitericsson%2Fnatours","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgitericsson%2Fnatours/lists"}