A Leaflet map with Node.js and MongoDB

Based on a number of comments, and the level of interest, I have updated this tutorial which I originally posted in 2014 addressing items, including, amongst other things, removing Mapbox libraries and updating the template engine from jade to pug. Please get in touch via email or comments if you have any feedback.

I wanted to explore the Node.js environment with a view to building a very simple mapping application. Initial searches didn’t reveal too much in the way of Leaflet, Node.js and MongoDB examples other than the OpenShift plug example by Steve Pousty back in 2014, which is a great start but I wanted a few more layers and an excuse to use the pug template engine (formerly jade). I attended an informative workshop by Steve Pousty at the 2014 FOSS4G event in Portland OR, same bundle, but with Flask rather than Node.js. I would highly recommend anyone starting out to spend some time on researching the fundamentals – here are a few links I found useful.

I decided to put a simple tutorial together in the hope that others might benefit from my efforts. Initially I found Node.js to be rather intimidating, it’s really not, but there are many third party Node.js programs, these vary from example to example and can be overwhelming. My suggestion would be to start off simple, figure out what you need and as you learn more, start exploring.The Node.js community is a great resource.

I am all about embracing best practice so if anyone has suggestions on how to improve on my content, please reach out, I would love to hear from you.

Here is what I want to achieve from my Node.js application:

  • Build something similar to the Mapbox Toggling layers example
  • Add point line and polygon layers to a Leaflet map
  • Store layers as GeoJSON in MongoDB
  • Use the pug (formerly jade) template engine to build HTML based on layers

In the example I will only have three layers but the design is intended to be scalable and should be able to accommodate more content without the need to build custom HTML.



If you use Windows or OS X you can get the latest version from the Node.js website it should be a pretty straight forward install and comes with the Node Package Manager, NPM which is really useful for installing many useful packages. You will be using NPM a lot but don’t worry it’s fairly straightforward.

For Debian based distributions like Ubuntu, Node.js is available using the package manager. On Ubuntu 14.04 the package for Node.js is nodejs instead of node, on Debian 7 nodejs is not available (thanks jaybe)

Open your terminal/command line and make a directory in which you will place your applications, I have made a directory called projects/nodejs. cd into the directory you have just made.

Next we are going to install the Express web framework – I found this framework really useful as it generates a collection of template files and folders that make sense and provide structure to our project.

These commands make the Express functionality available globally so we can access it from any test application projects we build in the future. The global installation of Node.js Packages have to be run as root, so must be run with sudo (thanks to jaybe for this reminder)


Creating a project

We are now ready to crate a project. If you are not already there, cd into the directory you made and think of a name for your new project, I am going with leaflet_map. To create your leaflet_map project, execute the following command, where leaflet_map is whatever name you have chosen for your project.

I recently tried this on Trusty (14.04) with no result and discovered I needed to install the nodejs-legacy package. It appears to only apply to Trusty (14.04) so if this applies to you, run the following command

This is kind of a magical moment as Node.js and Express get to work generating a project template for you. You should see a series of lines that begin with ‘create’ returned in the console. Take a look at the contents of your parent directory, you will notice there is now a directory with the name of your project. Take a look inside your project folder, you should see the following:

  • app.js – application nerve center
  • bin directory – internal workings
  • package.json – handles dependencies
  • public directory – location for images, javascripts and stylesheets
  • routes directory – kind of like a switchboard, handles and directs requests
  • views directory – where the HTML output is constructed

If you take a look in your views directory you will see a few files with a .jade extension, these are the jade template files and will be used to generate HTML. Jade has since changed its name to pug and I am assuming this will be reflected in the express setup in the near future, but, for now, simply change the .jade extension of these files to .pug. To learn more about the pug template engine take a look at https://github.com/pugjs/pug and jade-lang.com. Pug is a little weird at first but if you know some HTML you should be up and running in no time – the key to pug is indentation. If you would prefer not to use pug, you have many options, there are plenty of template engines to choose from including. You may have heard of haml, handlebars or mustache, now is a good time to configure your index.js if you would like to use one of these, you could also use the express ejs option which is more in-line with raw HTML.


Add Dependencies

Open the package.json file in your editor of choice, you will notice that it is a basic JSON file with a short description of the app and a list of the dependencies. Since we will be working with MongoDB we need to add two dependencies. In your package.json file type in the mongodb and mongoose dependencies seen below – don’t forget the trailing comma on all dependency lines apart from the last. Since jade has changed its name to pug, we need to replace the line “jade”: “-1.11.0”, with “pug”: “*”, . If you haven’t already done so, open the views folder and rename the jade file extensions to .pug. When working with JSON or GeoJSON there are some useful syntax checkers like http://jsonlint.com and http://geojsonlint.com, if you have any doubt about your json syntax, these are useful resources. Another handy JSON resource is the command line tool https://www.npmjs.org/package/jsonlint – it’ll point out where your syntax errors exist – then you can know whether it’s syntax or something else. The asterisks in the lines we have added instruct NPM to get the latest version of that dependency. Mongoose is a driver that Node.js uses to talk to MongoDB.

Save the edits you made to the package.json file. To install the dependencies we have added we need to tell NPM to review our package.json file and take the necessary steps to get our new dependencies plugged in. To do this, execute the following command from inside your project folder.

Before running our build, we need to adjust the index.js to reflect the pug template engine change we made – navigate to the routes folder and open index.js in your favorite text editor. Adjust the ‘view engine’ line app.js file to look like the following:

Navigate into the views directory and change all the .jade file extensions to .pug then run the following:

At this stage I received a string of ‘Error: EACCES,mkdir’ failures, the following link helped get these resolved https://github.com/npm/npm/issues/5869. The cogs will start turning and in a few seconds your new dependencies should be officially hooked up. At this stage you can run your application in the browser – execute the following line then navigate to http://localhost:3000 into your browser. If you are using a server, adjust local host to reflect your remote IP.

you should see the words ‘Express’ and ‘Welcome to Express’ in your browser and the following in your console:

To exit out of your application,  hit Ctrl-C.

If you are interested in seeing where the text displayed in your browser came from, take another look at the routes/index.js file, you should see the following:

At the start of the tutorial I compared the functionality handled by content in the routing directory to a switchboard. The index.js file receives a request from the URL http://localhost:3000 it then calls the res.render function which takes two arguments, firstly,  ‘index’ which instructs the application to use the index.pug template file in the views directory and secondly, a JSON object with a name of title and a value of ‘Express’. This is the text that displays in the browser, but lets see how that’s done by looking at the views/index.pug file

This is what the content of a pug template file looks like, notice the indentation. The first line imports anything in the layout.pug file, this is a nice feature because it means we can get a template structure setup in the layout.pug file and use this for consistency across our site. The block content line is telling the pug template engine where the content from the layout file needs to go. Next the title variable passed from routes/index.pug, which in this case is ‘Express’ is assigned to an HTML <h1> tag then under that, a paragraph <p> with the text ‘Welcome to’ and again our title parameter is passed in, so it will read ‘Welcome to Express’ – and that is the content displayed in your browser. If you are feeling confident, make some changes to the routes/index.js and views/index.pug files to reflect your own content. You really don’t have much to lose, so I would encourage making some edits – if you get totally lost, simply delete the folder and run express <new_project> and start again.

Up till now we have pretty much covered what you are likely to find in most Node.js tutorials, the next steps will move us in the direction of our mapping application.



In your browser, head over to https://www.mongodb.org/ to download the latest version of MongoDB. This link is a very informative MongoDB install resource – follow the install setup in this link. To start the MongoDB service execute the following command:

To stop the MongoDB service execute the following command:

While the service is running, open another terminal/command line and execute the following command. Starting and stopping mongodb as a service requires  root-access. If you used service you shouldn’t need another terminal window since it does it for you in the background and you can still use your terminal.

Something similar to the following should be returned in the console:

Test is the default, we will be changing that to a new database. I will not be going into detail on how to use MongoDB, please refer to the MongoDB documentation to learn more. Lets go ahead and create a database with the same name as our project – at the mongo prompt type the following.

This will get us an empty database by the name of leaflet_map

Lets add some GeoJSON data to MongoDB, we can also get some sample data from the MongoDB website. Notice I have added a name to each layer and placed double quotes around ‘name’, ‘type’ and ‘coordinates’ field names. We will add the GeoJSON data to a collection called layercollection. Run the following commands at the mongo prompt.

To view the collection, at the prompt run:

Now that we have spatial data in MongoDB lets get it wired up for us to use in our application.


The Node.js MongoDB connection

To setup our MongoDB connection, edit the routes/index.js file to include the following.

First we set the mongoose variable then below that, a connection to MongoDB  ‘mongodb://localhost/leaflet_map’.

Continuing with our edits to the routes/index.js file, we define the Mongoose schema which we will call JsonSchema and below that the Mongoose model which we will call Json. Notice in the Json model definition there are three arguments – I didn’t find mongoose documentation too helpful if you already had data in the database the first argument is a name the second is the schema and the third is the collection, in our case leaflet_map.

We now need to set up an app item that handles a request for MongoDB GeoJSON data based on the name of our layer, we are going to use http://localhost:3000/mapjson/<layer_name> to do this. You should be somewhat familiar with the GET home page handler we looked at earlier, and we can leave that here for reference.

We tell the handler that we want a URL called http://localhost:3000/mapjson that takes a layer name as an argument. We then confirm that the layer parameter exists and use the MongoDB findOne function to return one layer item where the name in the MongoDB database collection matches the name of the parameter. The findOne function is appended to the Json model we defined above.

Next we build a handler to get us all the layer names and return them as JSON. This handler is very similar to the handler above except we do not want to restrict the result to only one record so we use find rather than findOne. We are also not accepting parameters on which to base our result and lastly we only want the name field returned in the JSON array. We will use this handler to iterate through our layers and add them to the map with the help of our GeoJSON handler above.

Finally, we are going to setup a page to display based on a request for the http://localhost:3000/map/ URL. We are going to send a jmap JSON object and lat lng variables to the map.pug template. These will be used to iterate through and generate HTML based on our layers and center our map at the lat and lng coordinates provided. The lat lng coordinates could just as easily be stored in our MongoDB collection.

If you have been paying attention you will notice we are sending the JSON, lat and lng variables to a map.pug template that does not yet exist – lets go and create this file. But before we create the map.pug file lets take a look at our MongoDB data in the browser. Execute the following command.

Go to http://localhost:3000/mapjson – what do you mean you got a 404? well that’s because the http://localhost:3000/mapjson takes a layer name argument – try again with the following: http://localhost:3000/mapjson/points and you should get your points GeoJSON returned. Hopefully this is starting to make sense. Lets create our map.pug file so we can display something other than JSON.


Show me the map

If you are still with me at this point – well done, this is the part where I leave you hanging and tell you to buy my book – I’m only kidding, I don’t have a book. Lets press on and create a views/map.pug file, if you like you can copy the index.pug file and rename it. Here’s where we will get our hands dirty with some pug templating and build our map content.

The views/map.pug file is going to have a similar structure to the the Mapbox Toggling layers example with the exception of the pug Template iteration and calls to the handler URLs to return our JSON and GeoJSON data and, we will only be using the Leaflet library. We could put everything in one file like the example but let’s rather get our style sheet and JavaScript references setup in the layout.pug file.

Take a look at the pug template engine which is still linked to its jade roots at th time of writing this, to learn more about how to setup your content and the format you need to use, notice the indentation. In the views/layout.pug file you will see I have setup the JavaScript and style sheet references for your application. There is not much point in doing this for our example as we only have a one page application but you might use the layout.pug file to setup your bootstrap page template – assuming other applications you build may have multiple pages – this will get you a consistent layout throughout your site.

Let’s edit our views/map.pug file, I will break down the content into three parts, the first is the HTML content.

Again, notice the indentation, this is important when working with pug. If your indentation is not correct, depending on the location of the indentation you might receive the following error: unexpected token “indent”, or simply return a blank screen. The first two lines are where the file will inherit the content from the layout.pug file. Next we add an HTML map div element – so the pug template engine translates #map to <div id=’map’></div>. We then add HTML div elements for legend title and legend body. Notice the line beginning ‘each…’ this is where the template magic kicks in – if you recall in the routes/index.js file, we are passing in a JSON object called jmap – the pug template now has access to this jmap variable, so that enables us to loop through the layer names available to us based on the content of our MongoDB database and output a checkbox and label for each item.

I have added some style content to the /public/stylesheets/style.css file needed to position the map and legend content correctly so be sure to get that setup before running your final product. The full source code is available on GitHub.

In the second part of our views/map.pug file we setup the Leaflet content and you will notice in the setView function we have added lat and lng arguments, these are being passed in from the routes/index.js file. The final four lines are where the handler magic happens, we make a getJSON request from /maplayers for the JSON that contains our layer names. Once we have our layer names we use the jQuery each function to iterate through our names and add arguments to the addLayer function call. The first argument sets up a Mapbox feature layer – using the loadURL function it makes a request from the mapjson/ handler we setup and uses the layer name from the each iteration as an argument. The final argument is the layer name itself.

The final part of the map.pug file is the addLayer function. The first part of this function adds out point line and polygon layers to the map and binds a popup and style to each layer. Right under that is where we append a click function to the layer check boxes we created in part 1 above – so each checkbox represents a layer that the user can toggle to turn that particular layer on or off.

Navigate to your public folder then populate the style.css file with the following:

That’s it, you are now ready to run your application, if you are not already there, cd to your project directory and run.

Head over to your browser and display your Leaflet Node.js application http://localhost:3000/map.



Depending on what you have in mind for your application build, you can construct request handlers in the routes/index.js file to handle data requests and page displays. If you recall from our example, we setup a /mapjson handler that takes a layer name as an argument to return GeoJSON for a particular layer. We also setup a /maplayers handler that returned the JSON for all our layer names, of course, we could adjust this to include other content such as alias names or style information. By combining URL handlers and the power of the pug template engine we have all the JSON we need at our disposal to use in JavaScript and the ability to generate considerable amounts of HTML on the fly.

Node.js is fun to work with and might just be my new favorite framework, I am definitely going to spend more time getting to know it better and explore some of the many programs that are available to extend its functionality.

The full source code is available on GitHub


  56 comments for “A Leaflet map with Node.js and MongoDB

  1. December 9, 2014 at 12:24 pm

    Thanks for the tutorial! It was a good splash into Node and MongoDB for me. I did have to do a little tweaking at the end to get the map to display. I may have missed something when typing in the code by hand, but here is a small tweak to display the map in full screen:

    Update views/map.jade so that the map legend title is located in the same div as the leg_items:

    block content
    span#leg_items Map Legend
    each layer, i in jmap
    input(type=’checkbox’ id=’#{layer.name}’)
    span#leg_items #{layer.name}

    Update public/stylesheets/style.css to the following:

    html, body, #map {
    height: 100%;

    body {
    padding: 0;
    margin: 0;

    #leg {
    position: absolute;
    top: 10px;
    right: 20px;
    background-color: rgba(255,255,255,0.9);
    padding: 10px 15px;
    border: 1px solid;
    border-radius: 10px;

    • denelius
      December 9, 2014 at 2:06 pm

      Christopher – thanks for your comment, both #leg_items (id for HTML span element) and the legend title text ‘Map Legend’ are part of the same div (#leg_title). I am not too sure why you needed to make those changes but I’m happy you got it working in the end. I hope your comment might be useful to others

  2. jaybe
    December 17, 2014 at 2:59 am

    Thanks for the tutorial. Just started with it, but found some issues:
    – On Ubuntu 14.04 the package for Node.js is nodejs instead of node, on Debian 7 nodejs is not available
    – The global installation of Node.js Packages have to be run as root, so “npm install -g express” and “npm install -g express-generator” must be run with sudo
    – Starting and stopping mongodb as a service requires also root-access

    • denelius
      December 17, 2014 at 10:00 am

      Thanks jaybe – this is really useful feedback! I will put some time aside to update the post based on your comments

  3. chadwilcomb
    March 23, 2015 at 10:43 am

    Thanks for this tutorial, it is a really nice intro to node/express generato, jade templates and leaflet integration. Very easy to follow. Thank you.

  4. Sergio
    May 5, 2015 at 11:07 am

    Thanks for the tutorial, nice!!

  5. GMiniTV
    September 29, 2015 at 12:37 am

    Great tutorial!

    Only point of criticism I would make is that perhaps you could go into brief detail about the MapBox library and how you’re using the Leaflet API directly from MapBox. They are two separate things.

    Perhaps you could tell us the difference between Leaflet and MapBox?
    (one is integrated into the other)

    Either way, awesome stuff and a great read/experiment!
    Glad to see community contributions!

  6. Jose
    October 7, 2015 at 12:47 pm

    Thanks for the tutorial but in the last step in :


    I get null!

    Thanks for any help!

    PS: I change the port, but I think that is not the problem because with points, lines,… is ok!

    • denelius
      May 16, 2016 at 12:08 pm

      Hi Jose – thanks for leaving a comment, try the updated post content. If you are seeing the point line and poly features, then the issue might be with the mapbox part of the tutorial, I have changed this to use leaflet only. Are you getting any browser debug errors?

  7. October 20, 2015 at 11:31 am

    Thank you so much..its working for me too..
    very important key steps ..im very new to mongodb and nodejs…if i will have issue i will contact you in future..

    thank you…

  8. tine
    October 21, 2015 at 9:55 am

    Hi. I tried both the tutorial and the code from your repository, and it kept saying
    TypeError: C:\Bitnami\meanstack-3.0.6-1\projects\nodejs_leaflet\views\map.jade:7
    5| span#leg_items Map Legend
    6| #leg
    > 7| each layer, i in jmap
    8| input(type=’checkbox’ id=’#{layer.name}’)
    9| span#leg_items #{layer.name}
    10| br

    Cannot read property ‘length’ of undefined.

    I’m trying to learn nodejs and mongodb, and I’m not sure I quite understand it yet.

    • denelius
      May 16, 2016 at 12:05 pm

      Hi tine – so it looks like you are getting an undefined variable in jmap, this could mean that you have a typo in the views/index.js file. Try the updated post content, it might fix your issue. keep at it

  9. October 22, 2015 at 2:16 am

    Hi, Thanks for the tutorial. e.preventDefault(); is causing errors. Do you have any idea how to fix it ?

    /home/harry/lammadog/leaflet_map/views/map.jade:29 27| //.addTo(map); 28| $(‘#’ + name).click(function(e) { > 29| e.preventDefault(); 30| e.stopPropagation(); 31| e.stopImmediatePropagation() 32| if (map.hasLayer(layer)) { unexpected text ;

    Error: /home/harry/lammadog/leaflet_map/views/map.jade:29
    27| //.addTo(map);
    28| $(‘#’ + name).click(function(e) {
    > 29| e.preventDefault();
    30| e.stopPropagation();
    31| e.stopImmediatePropagation()
    32| if (map.hasLayer(layer)) {

    unexpected text ;

    at Object.Lexer.fail (/home/harry/lammadog/leaflet_map/node_modules/jade/lib/lexer.js:887:11)
    at Object.Lexer.next (/home/harry/lammadog/leaflet_map/node_modules/jade/lib/lexer.js:947:15)
    at Object.Lexer.lookahead (/home/harry/lammadog/leaflet_map/node_modules/jade/lib/lexer.js:113:46)
    at Parser.lookahead (/home/harry/lammadog/leaflet_map/node_modules/jade/lib/parser.js:102:23)
    at Parser.peek (/home/harry/lammadog/leaflet_map/node_modules/jade/lib/parser.js:79:17)
    at Parser.tag (/home/harry/lammadog/leaflet_map/node_modules/jade/lib/parser.js:773:22)
    at Parser.parseTag (/home/harry/lammadog/leaflet_map/node_modules/jade/lib/parser.js:759:17)
    at Parser.parseExpr (/home/harry/lammadog/leaflet_map/node_modules/jade/lib/parser.js:211:21)
    at Parser.block (/home/harry/lammadog/leaflet_map/node_modules/jade/lib/parser.js:729:25)
    at Parser.tag (/home/harry/lammadog/leaflet_map/node_modules/jade/lib/parser.js:838:24)
    at Parser.parseTag (/home/harry/lammadog/leaflet_map/node_modules/jade/lib/parser.js:759:17)
    at Parser.parseExpr (/home/harry/lammadog/leaflet_map/node_modules/jade/lib/parser.js:211:21)
    at Parser.parse (/home/harry/lammadog/leaflet_map/node_modules/jade/lib/parser.js:122:25)
    at parse (/home/harry/lammadog/leaflet_map/node_modules/jade/lib/index.js:104:21)
    at Object.exports.compile (/home/harry/lammadog/leaflet_map/node_modules/jade/lib/index.js:205:16)
    at handleTemplateCache (/home/harry/lammadog/leaflet_map/node_modules/jade/lib/index.js

    • denelius
      May 16, 2016 at 12:00 pm

      Hi Harry – thanks for leaving a comment, please try the updated post content or remove the e.prevent and e.stop lines

  10. Prachi
    November 20, 2015 at 1:26 pm

    I tried and followed your tutorial, but I cannot see the map. I can see the #legs and #leg_items on the top right but no map.
    I checked the mapbox token and it should be working fine.
    Can someone help? What could be possibly wrong?
    P.s. I am using windows machine and I checked for any errors or anything but none

    • denelius
      May 16, 2016 at 11:57 am

      Hi Prachi – this sounds like a stylesheet related issue, check the stylesheet is in the right location and that it has the correct content – are you getting any errors in the browser debug mode?

    • vaibhav
      July 29, 2016 at 12:59 pm

      prachi i got the same error just check your console you will see the error. bootstrap.min.css was blocked in my case and hit the same url in other web browser it was working fine in internet explorer but not in google crome and mozila but i changed the proxy setting and it works fine for me now in every browser

    • Sarvesh
      June 13, 2017 at 6:39 pm

      I’m also getting the same error. Can anyone tell me how to solve it?

      • denelius
        June 13, 2017 at 9:06 pm

        Hi Sarvesh, please can you confirm the error. If you are referring to no map display but legend present, please confirm css file is in place and leaflet libraries are correct

  11. Ian
    January 7, 2016 at 3:02 am

    Hello! I’d just like to clarify on the connect to mongodb. The part ‘Edit etc/mongo.conf file’, where exactly would I find that? Or do I have to make that directory? If so, where would I place that, on the mongo folder or inside the data/mongo folder?

    Thanks for this great tutorial anyway. 🙂

    • denelius
      May 16, 2016 at 11:55 am

      Hi Ian – have a look at the updated post content, Im hoping it will resolve both of your comments, the mongo install seems to be a little easier since I first wrote the post and my guess is the the blank map related to one of the mapbox libraries which I have since removed in favor of a leaflet one

  12. tdean
    March 1, 2016 at 5:33 pm

    I’m coming to the party a little bit late. Let me start by saying that this is a super interesting post. Chalk me up under the “mind blown” group. I’m a map developer that does traditional html/bootstrap layouts mainly in the ESRI or leaflet APIs world. I completed this tutorial and the application runs. However, I can’t understand how the leaflet components of this application fit in. It appears to me like this is developed using the MapBox API. I checked the html script references and cannot find a script reference for leaflet. Am I missing something?
    Thanks for sharing such an awesome tutorial!

  13. April 12, 2016 at 9:34 am

    i got this error
    mapbox.js:1 GET http://a.tiles.mapbox.com/v4/examples.map-i86nkdio.json?access_token=pk.eyJ1IjoibmV3ZmllbGRzIiwiYSI6Ikk3TmFfYWMifQ.yxfeME9vJaT2GyCbnzsBzw 404 (Not Found)i @ mapbox.js:1e.exports @ mapbox.js:6e.exports._loadTileJSON @ mapbox.js:6L.Map.extend.initialize @ mapbox.js:6e @ mapbox.js:1e.exports.map @ mapbox.js:6(anonymous function) @ map:2
    mapbox.js:6 could not load TileJSON at http://a.tiles.mapbox.com/v4/examples.map-i86nkdio.json?access_token=pk.eyJ1IjoibmV3ZmllbGRzIiwiYSI6Ikk3TmFfYWMifQ.yxfeME9vJaT2GyCbnzsBzwe.exports.log @ mapbox.js:6(anonymous function) @ mapbox.js:6(anonymous function) @ mapbox.js:1a @ mapbox.js:6o @ mapbox.js:1

    • denelius
      May 16, 2016 at 11:52 am

      Hi zezend thanks for leaving a comment – I have updated the post, please try the new content, I have removed mapbox references in favor of only using leaflet ones

  14. Dhamo
    May 26, 2016 at 5:59 am

    Hi I need to build a choropleth map usinng Mapbox, Nodejs and Elasticsearch. I need choropleth map based on the zoom level, if it is country level zoom then choropleth is for each country. or if it is state level zoom it is changed to state level choropleth upto city level zoom.. please help on this

  15. ingrid
    June 29, 2016 at 11:23 am

    /* GET Map page. */ do you mean app.get, not router.get (router is not defined)?

    • denelius
      July 16, 2016 at 1:15 pm

      Hi Ingrid – good catch, thanks, I have edited the post

  16. vaibhav
    July 29, 2016 at 12:52 pm

    hi denelius many many thanks for this article and please share some idea how to use this application with angular js because i want to create an application using leaflet and mean stack to show some data based on the longitude and latitude and i want to use simple HTML instead to any of these template engines like (Jade,Pug) ..waiting for your reply 🙂


    • denelius
      July 29, 2016 at 1:43 pm

      Hi vaibhav I cant offer too much advice on introducing Angular to the stack – I would like to tinker with that in the near future but have not yet had a chance to do so. Check out some of the MEAN stack tutorials, a few of them look quite good. You dont have to use Pug, I actually prefer plain HTML too but wanted to introduce different options so people could see how its done – in your index.js adjust your view engine line from app.set('view engine', 'pug'); to app.set('view engine', 'ejs'); you should then be good to go with vanilla HTML – you will need your files to have a .ejs extension

  17. Marco
    August 1, 2016 at 10:46 pm

    Hi Denelius,
    first of all: thanks a lot for sharing your knowledge on this way. This is really helpful and saved me a lot of time. I really wonder how you figured out how to perform all these steps correctly.
    When you do:
    app.get(‘/map’, function(req,res) {
    var db = req.db;
    I don´t really get why the request object has an db property and where it gets it from?
    I see that you connect to the database via mongoose.connect, but how is this connection passed to the request object?


    • Marco
      August 2, 2016 at 12:29 pm

      Today I figured out that it is also working without the line
      var db = req.db;

      If I do
      app.get(‘/map’, function(req,res) {

      It says ‘undefined’.

      Maybe it´s just an leftover from earlier steps?

      • denelius
        August 17, 2016 at 10:22 pm

        Hi Marco – thank you for the feedback, you are correct, the db var is never being called and so I have removed it. I have also run through the tutorial again from start to end and cleared up some content I had rushed over. I have pushed the content to github.

  18. January 31, 2017 at 10:49 pm

    I am new to node js any advice on this error as I might have not fully understood the set up of the index.js file.

    Error: ENOENT: no such file or directory, open ‘/Users/danielhill/map/leaflet_map/views/layout.jade’
    at /Users/danielhill/map/leaflet_map/views/error.pug line 1
    at Object.fs.openSync (fs.js:558:18)
    at Object.fs.readFileSync (fs.js:468:33)
    at Object.read (/Users/danielhill/map/leaflet_map/node_modules/pug/lib/index.js:78:22)
    at Function.read (/Users/danielhill/map/leaflet_map/node_modules/pug-loader/index.js:66:47)
    at /Users/danielhill/map/leaflet_map/node_modules/pug-loader/index.js:23:22
    at walkAST (/Users/danielhill/map/leaflet_map/node_modules/pug-walk/index.js:13:26)
    at /Users/danielhill/map/leaflet_map/node_modules/pug-walk/index.js:21:16
    at Array.map (native)
    at walkAST (/Users/danielhill/map/leaflet_map/node_modules/pug-walk/index.js:20:29)
    at load (/Users/danielhill/map/leaflet_map/node_modules/pug-loader/index.js:12:10)

    • denelius
      February 27, 2017 at 11:01 pm

      Hi Dan, it looks like you might be mixing .pug and .jade files, if your view engine is set to pug in your index.js file, the files in your view folder will need a .pug file extension. If your view engine is set to jade in your index.js file, the files in your view folder will need a .jade file extension. – I hope this helps

    • Jeffc
      July 15, 2017 at 4:12 pm

      I had the same error due to an old version of pug. Update it using npm:

      > npm uninstall pug
      > npm install pug –save

      Also note that in current Express the view engine is set in app.js not index.js.

      • Jeffc
        July 15, 2017 at 4:24 pm

        One other step. Remove “pug”: “*”, from package.json before re-installing pug. That “*” parameter causes the old pug to be installed.

  19. Ismael
    April 15, 2017 at 2:41 am

    Hi, I get this error when I run http://localhost:3000/map, thanks a lot, regards

    Not Found

    Error: Not Found
    at C:\Users\PC\Desktop\mapas\expressjs\leaflet_map\app.js:30:13
    at Layer.handle [as handle_request] (C:\Users\PC\Desktop\mapas\expressjs\leaflet_map\node_modules\express\lib\router\layer.js:95:5)
    at trim_prefix (C:\Users\PC\Desktop\mapas\expressjs\leaflet_map\node_modules\express\lib\router\index.js:317:13)
    at C:\Users\PC\Desktop\mapas\expressjs\leaflet_map\node_modules\express\lib\router\index.js:284:7
    at Function.process_params (C:\Users\PC\Desktop\mapas\expressjs\leaflet_map\node_modules\express\lib\router\index.js:335:12)
    at next (C:\Users\PC\Desktop\mapas\expressjs\leaflet_map\node_modules\express\lib\router\index.js:275:10)
    at C:\Users\PC\Desktop\mapas\expressjs\leaflet_map\node_modules\express\lib\router\index.js:635:15
    at next (C:\Users\PC\Desktop\mapas\expressjs\leaflet_map\node_modules\express\lib\router\index.js:260:14)
    at Function.handle (C:\Users\PC\Desktop\mapas\expressjs\leaflet_map\node_modules\express\lib\router\index.js:174:3)
    at router (C:\Users\PC\Desktop\mapas\expressjs\leaflet_map\node_modules\express\lib\router\index.js:47:12)
    at Layer.handle [as handle_request] (C:\Users\PC\Desktop\mapas\expressjs\leaflet_map\node_modules\express\lib\router\layer.js:95:5)
    at trim_prefix (C:\Users\PC\Desktop\mapas\expressjs\leaflet_map\node_modules\express\lib\router\index.js:317:13)
    at C:\Users\PC\Desktop\mapas\expressjs\leaflet_map\node_modules\express\lib\router\index.js:284:7
    at Function.process_params (C:\Users\PC\Desktop\mapas\expressjs\leaflet_map\node_modules\express\lib\router\index.js:335:12)
    at next (C:\Users\PC\Desktop\mapas\expressjs\leaflet_map\node_modules\express\lib\router\index.js:275:10)
    at SendStream.error (C:\Users\PC\Desktop\mapas\expressjs\leaflet_map\node_modules\serve-static\index.js:121:7)

    • denelius
      June 13, 2017 at 9:04 pm

      Hi Ismael, do you have a map.pug file in your views directory?

  20. john
    May 15, 2017 at 9:39 pm


    sorry if my question is naive – I followed your post till the end but when I’m visiting localhost:3000/map I’m getting just a bunch of checkboxes and the title “Map Legend”. Do I need to change map.pug and add a key for leaflet or is there anything else I’m missing ?

    • denelius
      June 13, 2017 at 9:02 pm

      Hi John, sorry for the delay in responding, are you able to send an error message? Please check your page using your browser dev tools to see if there are any missing libraries. If I were to guess, I would say the leaflet library is missing, this should be in the .pug template file views/layout.pug. The other item is to make sure you have a css file in public/stylesheets/style.css – I hope that helps

    • Joe
      November 16, 2017 at 6:45 am

      Substitute the newer leaflet css and js files in the header (layout.pug) and it should work:




  21. May 29, 2017 at 3:26 am

    great tutorial.. i have run this code,, and work properly with url localhost:3000/map.

    i wanna try to collaborate with ionic framework. any one have do that ?

    • denelius
      June 13, 2017 at 8:37 pm

      Hi taufik – thanks, I have not explored the ionic framework, good luck, you are heading in a great direction

  22. milan
    June 12, 2017 at 8:09 pm

    Thanks for the tutorial.

    I tried your example, without changing anything. but webpage does not show map. Only map legend for maps is there.
    I am using windows 10 by the way.

    • denelius
      June 13, 2017 at 8:53 pm

      Hi milan, are you able to provide an error message? When you say without changing anything, did you clone the files from GitHub or follow the tutorial? The error message should give you an indication of what went wrong. Please check your mongo connection and ensure it is working independently. Check you browser dev tools for any other clues, perhaps missing libraries or a missing css?

  23. kst
    September 11, 2017 at 6:03 pm

    Thanks for the great tutorial! I have been trying to get this working but I seem to be having an issue with the scripts in map.pug! Is the open-curly really an unexpected character? Am i doing something wrong?

    Thank you for your tutorial!!! It has been very helpful!

    Error: mapproject/views/map.pug:30:34
    28| function addLayer(layer, name) {
    29| var leaf_layer;
    > 30| if (layer.type == “MultiPoint”) {
    31| leaf_layer = L.geoJson(layer, { pointToLayer: function (feature, latlng) {return L.circleMarker(latlng, layer.style); }})
    32| leaf_layer.bindPopup(layer.type);
    33| } else if (layer.type == “MultiLineString”) {

    • denelius
      January 11, 2018 at 9:51 pm

      Hi kst – this might be related to indentation on line 30

  24. Atul
    October 9, 2017 at 10:41 am

    Hi, I get this error on console when I run http://localhost:3000/map,

    ReferenceError: L is not defined

    • denelius
      January 11, 2018 at 9:50 pm

      Hi Atul, this looks like an issue with your Leaflet library path

    • June 23, 2018 at 9:58 pm

      Hi I received the same error but it had to do with indentation on the pug file. In fact all my errors had to do with indentation on the pug file. In your pug files ensure you’re not using spaces and you’re using tabs. You can check your leaflet scripts by going to the site directly https://cdn.leafletjs.com/leaflet/v0.7.7/leaflet.js and checking if the script shows up. If it does then you’re sure your path is ok.

      Also when your page loads view the source and see if the pug file is parsed properly. In my case because title was on the same level with head. The head tags were closed and my scripts ended up within the title tag. As soon as I corrected the indentation my map loaded perfectly

  25. April 29, 2018 at 11:41 pm

    Hey, I get a white screen with only the legend in the upper right hand corner. In the NPM terminal window I get an error that says “You should not have pug tags with multiple attributes.” Do you know what’s going on?

    • denelius
      June 24, 2018 at 10:21 am

      Hi Patrick – This looks like it relates to your template pug file/s – does the error provide a line number? Can you post the code? Take a look at this url https://github.com/pugjs/pug/issues/2926

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.