Leaflet weighs 40 kB gzipped, and its npm entry point is the unminified build
GitHub describes it as 🍃 JavaScript library for mobile-friendly interactive maps 🇺🇦. The repository metadata lists JavaScript as its primary language. The metadata lists the BSD-2-Clause license. This article stays within the project description and details documented in the GitHub repository README.
At a glance
- What is it?
- Leaflet is a BSD-2-clause JavaScript map library created in September 2010 by Volodymyr Agafonkin, whose README opens with an appeal about the war in Ukraine rather than an install command. The library is small, browser-only and framework-agnostic, its published entry point is the readable source build, and the repository's package.json is sitting on a 2.0.0 alpha.
- Who is it for?
- Use Leaflet when you want to own the map surface, the tile budget and the rendering code, and when a browser DOM library is the right fit for your stack. Look elsewhere when you need a bundled tile service, server-side rendering of the map, or a data layer, because none of that is in this repository.
- Can I use it commercially?
- Yes. BSD-2-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 10 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 25, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The first screen of the README is a statement, not a setup guide
Open the README and the first thing you read is not an install command. It is an appeal about the war in Ukraine, written by the Leaflet maintainers, naming the library's creator Volodymyr Agafonkin as a Ukrainian citizen living in Kyiv, asking readers to demand sanctions, protest and donate to Ukrainian charities such as Come Back Alive. Underneath that, the README says Leaflet was created in September 2010, presents itself as an open-source JavaScript library for building interactive maps, and sends you to the official website for docs, tutorials and downloads. There is no npm install line anywhere in it. That is a governance fact rather than a technical one, and it has a practical edge for anyone evaluating the project: the README is a statement of who maintains it, and the install instructions, the API reference and the download page are three separate destinations you have to visit instead.
The published entry point is dist/leaflet-src.js
The publish configuration is what tells you what you actually get from the registry, and it is small enough to read in one go:
"exports": {
".": "./dist/leaflet-src.js",
"./styles.css": "./dist/leaflet.css"
},
"style": "dist/leaflet.css",Two decisions sit in those five lines. The main export is the source build rather than a minified bundle, so what your bundler receives is the readable version of the library. And the stylesheet is a second specifier rather than something imported for you, so a setup that ignores CSS imports ends up with an unstyled map. The files array widens the picture, since it ships the dist directory, the src directory, CHANGELOG.md, and explicitly leaves out the zip and the leafdoc files:
"files": [
"dist",
"src",
"!dist/leaflet.zip",
"!*.leafdoc",
"CHANGELOG.md"
],The consequence for packaging is that the minified archive is not in the npm tarball at all. The README points to the download page for Leaflet downloads, including the built main version, which is where the small bundle lives.
The 40 kB figure is a budget, not a boast
The README claims Leaflet weighs just about 40 kB of gzipped JS plus 3.2 kB of gzipped CSS and still carries the mapping features most developers need. In a project with that kind of claim, the interesting part is what holds the number in place. The repository root carries a bundlemon configuration file, bundlemon appears among the devDependencies, and package.json exposes a bundlemon script. Husky and lint-staged are there as well, so pre-commit hooks are part of the workflow. What that adds up to: the size in the README is checked mechanically, and a change that grows the bundle is a failing check rather than a debate. For a reader weighing the library against a heavier mapping stack, that is the more useful number than the total, because it is a maintained ceiling. For a plugin author it is also a boundary, since anything you add lands outside the budget the core library is holding.
The test suite runs in Chromium through Playwright
Leaflet's tests are browser tests, and the devDependencies say so plainly: @vitest/browser, @vitest/browser-playwright, playwright, a coverage package on v8 and a UI package, alongside chai, sinon, prosthetic-hand and ui-event-simulator. The script that runs them is a single line:
"test": "vitest --project=chromium",Consequences for a contributor: running the suite locally means a browser is available to Playwright, and a green run reflects one browser project rather than a matrix. The coverage and UI variants are separate scripts, so interactive debugging is opt-in rather than the default. Consequence for anyone depending on Leaflet: every one of those packages is a devDependency, which means the assertion and simulation libraries never reach your application, and the only thing your bundle sees is the library itself plus the stylesheet. The spec/ directory at the repository root is where that suite lives, next to src/ and build/.
The API reference is generated, then checked for integrity
Documentation is not maintained as a separate tree of prose. leafdoc is a devDependency, and the docs script runs two steps in sequence:
"docs": "node ./build/docs.js && node ./build/integrity.js",So the reference on the website is generated from the source comments, and an integrity pass runs immediately after the generation. Anyone who wants to correct a description in the reference is editing a source comment, not a documentation file, and a mismatch between the two is what the second script is positioned to catch. The repository makes the same point structurally: docs/ and debug/ sit beside build/, and there is a PLUGIN-GUIDE.md and an FAQ.md at the root for the questions that do not belong in generated reference. For a plugin author, PLUGIN-GUIDE.md is the file in the repository that tells you what is expected of a plugin, and the README's promise of a huge amount of plugins resolves to the plugin list published on the website, which it does not rank.
main is a year past the last tag, and that tag is an alpha
The version field in package.json reads 2.0.0-alpha.1. The release history around it is a prerelease line rather than a shipping one: v2.0.0-alpha on 2025-05-18, v2.0.0-alpha.1 on 2025-08-16, and a development snapshot dated 2025-09-17. The last push to main came on 2026-09-21, which means the branch has moved well past the newest tag without a new one. That combination is the thing to hold onto when you decide how to depend on this. A 2.0 line exists only in alpha form, so there is no stable 2.0 to pin to, and the README's separate mention of a built main version on the download page tells you the stable line lives outside this package.json. Pin the exact version you tested rather than a range, and if you take the alpha, budget for reading the changelog yourself, since CHANGELOG.md ships in the tarball and RELEASE.md in the repository is the process the maintainers follow.
No framework binding ships here, and the plugin list is where the rest lives
The questions people bring to this library are mostly about the surrounding stack: React, Next.js, Angular, React Native, R, Obsidian, printing, offline use. Leaflet itself is a browser JavaScript library with a documented API and a plugin list, and the repository contains no binding for any of those environments. That is a deliberate division rather than a gap. The cost lands on you: a framework wrapper is a separate project with its own release cycle, and printing, clustering or offline behaviour is a plugin decision the README leaves open by pointing at the published list without recommending anything on it. Offline use deserves a specific warning, because the README does not document tile caching at all and neither does this repository's file list. The API reference and the plugin list on the website are the only sources in scope, so check there before designing around offline behaviour.
Editorial conclusion
Use Leaflet when you want to own the map surface, the tile budget and the rendering code, and when a browser DOM library is the right fit for your stack. Look elsewhere when you need a bundled tile service, server-side rendering of the map, or a data layer, because none of that is in this repository. Verify three things before you commit to a version: which line the download page is serving against the 2.0.0-alpha.1 in package.json, whether your framework binding is a separate project you now maintain, and whether the plugin you rely on for clustering, printing or offline behaviour is listed at leafletjs.com, since the README does not rank plugins or document offline use.
Frequently asked questions
How to install Leaflet?
The package on npm is leaflet, and its main export points at dist/leaflet-src.js with the stylesheet available as a separate specifier. The README does not contain an install command and sends you to the website, where the download page also carries the built main version.
How do you use Leaflet.js?
You create a map on a page and add layers to it through the documented API, which is published as a reference and generated from the source comments by leafdoc. The build script that produces that documentation also runs an integrity check over the result.
How do you use Leaflet in React?
Leaflet ships no framework binding. It is a browser JavaScript library with a documented API, and the README points to the API reference and the published plugin list for anything beyond the core, so a React wrapper is a separate project you choose and maintain.
How do you use Leaflet offline?
The README does not document offline use, and nothing in the repository covers tile caching. The two sources in scope are the API reference and the plugin list published on the website, so check the plugin list before designing around offline behaviour.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/leaflet-leaflet)