mapcn: free React map components sitting on a basemap you still have to license
Beautiful map components. 100% Free, Zero config, one command setup.
At a glance
- What is it?
- mapcn is a MIT licensed set of React map components built on MapLibre GL and handed out through a shadcn registry rather than an npm package. The component code is genuinely free to copy, but the default backdrop comes from CARTO under separate terms, and the routes and markers features draw what you feed them rather than compute anything themselves.
- Who is it for?
- mapcn fits a React application that already leans on shadcn and needs a map surface with markers, popups, drawn geometry, and the four standard controls. Adopt it with clear eyes about the division of labour: you supply tile credentials and their licensing, route geometry, any geocoding, marker strategy at scale, and manual updates to the code you copied, because the repository has no tagged releases to fall back on.
- Can I use it commercially?
- Yes. MIT 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 27 days ago.
- What is it written in?
- Mainly TypeScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 3, 2026, and from our analysis. They are not legal advice.
Editorial analysis
The MIT license stops at your code, not at the tiles underneath it
The LICENSE file in this repository covers the component source and nothing beyond it. The pixels your map paints come from a separate party: the project states that it uses CARTO Basemaps, which are based on OpenStreetMap data. The licensing split is spelled out in three lines. Commercial use requires a CARTO Enterprise license, and the project links to a demo request form for pricing. Non-commercial use is free for CARTO grantees under their published basemap terms. So the free and open source claim in the repository description is accurate about the components and silent about the default backdrop a visitor sees on screen, which is exactly the kind of gap that only surfaces when a product goes live.
The README does name replacements, which is more than most component libraries bother to do. You can switch to OpenStreetMap tiles or to any other MapLibre compatible tile provider, with MapTiler and Stadia Maps given as examples. What it does not document is the switch itself. There is no configuration key, no prop, and no provider picker anywhere in this repository, so choosing where your tiles come from is work you do in your own application code. The consequence is concrete for a reader: a free component library can put you on a paid tile contract by default, and the bill, the attribution requirements, and the traffic limits all land on your project rather than on this one.
The registry build is two commands and the second one rewrites what the first wrote
Nothing is published to a package registry as source you can import. Instead, the components are compiled into a shadcn style registry, and that build is deliberately two steps:
npx shadcn build -o ./public/r && npx tsx scripts/fix-registry-imports.tsThe first half asks the shadcn CLI to emit the component files into ./public/r. The second half runs a repository script whose only job, judging by its name, is to fix up the import paths in the output that was just generated. Both halves are joined with a shell and, so a build that stops after the first command leaves a directory of files with whatever paths shadcn produced. Two consequences follow for anyone consuming this. The files you end up with are build output rather than the source that lives under src/, so a stack trace from the installed component will point at generated code that does not line up with the repository you cloned. And nothing in the repository explains what scripts/fix-registry-imports.ts actually rewrites or how you would verify that it ran correctly, which means a partially built registry is a failure mode you can only detect by using the components.
The shadcn configuration that drives all of this sits at the repository root as components.json, next to registry.json. The surrounding root files show where the project's own conventions live: next.config.ts, postcss.config.mjs, eslint.config.mjs, .prettierrc, and tsconfig.json, with prettier-plugin-tailwindcss handling class ordering, plus an AGENTS.md that is present but whose contents are not reproduced in the README.
React is pinned to 19.2.3 while almost every other dependency floats on a caret range
Look at the version strings in package.json and one asymmetry stands out. Nearly everything moves: next at ^16.2.7, maplibre-gl at ^6.3.0, tailwindcss at ^4, shadcn at ^3.6.2, recharts at ^2.15.4, next-themes at ^0.4.6, lucide-react at ^0.562.0. React and react-dom are the exception, written as the exact string 19.2.3 with no range operator at all. That difference has teeth in practice. A fresh install can drag the framework and the map engine forward across minor versions while your React patch level stays welded to whatever this repository chose, and the type definitions float too, with @types/react at ^19 and @types/node at ^20 sitting next to a fixed runtime. A stack assembled that way is not reproducible from the manifest alone, so if a new MapLibre minor changes a method signature you call, the pin on React tells you nothing about why your map broke.
The larger limit is packaging. package.json declares the package private and carries the version 0.1.0, and the repository publishes no GitHub releases, so there is no named artifact to place in your own dependency list and no version range to write down in a design document. What you take from here is a copy that lives inside your own source tree, which means the upgrade decision is per component and entirely yours. The repository itself is a Next 16 application on that fixed React, serving the documentation site and producing the registry payload.
Routes means drawing a path you already have, not computing one
Routes appear in the feature list as a single short line: draw routes and paths on your maps. Read literally, and that is the whole claim. Nothing in this repository documents where a path geometry originates. No routing service client is named, no road network snapping is described, no hosted routing API is referenced, and no turn by turn behaviour is documented. The single signal pointing at data shapes is @types/geojson in the development dependencies, which tells you GeoJSON types are part of the typing surface while saying nothing at all about a source for the coordinates.
So the consequence for a reader is direct and worth stating before you plan around this feature. If you want a route, one of three things has to happen outside this project: you call a routing service you sign up for and pay for, you precompute geometry yourself, or you hand the component a path that already exists in your data. In every case the component draws it. Turn instructions, leg lists, arrival estimates, and rerouting are all your code, and if your product needs a navigation experience rather than a line on a map, this is the wrong building block. Treat the routes item as a rendering slot that accepts a geometry, and budget separately for the routing brain, because nothing in this repository will supply it or fail loudly when it is absent.
Four controls, and no documented answer for ten thousand markers
The marker system is described as rich, covering markers and popups with tooltips and labels, and the component set is meant to be composed rather than configured, which is the strength and also the boundary. The controls are enumerated and finite: zoom, compass, locate, and fullscreen. That list is short and closed. A scale bar, a pitch toggle, an attribution switch, a geolocate watch mode, or a custom control does not appear on it, so each one you want becomes a component you write and maintain yourself.
The marker side has a gap that will show up under load. Nothing here documents clustering, so a dataset with thousands of points has no documented path to decluttering, and the GeoJSON typing gives you valid shapes rather than a strategy for rendering them at density. There is also no address search, no place lookup, and no geocoder integration named anywhere, which means a search box next to the map is something you assemble against a service this project does not include or configure.
The predictable outcome across both areas is a division of labour worth naming before you commit. mapcn supplies the surface, the marker primitives, and a fixed set of controls; your application supplies the data, the services, the licensing for those services, and the decisions about what the map shows and when. That arrangement is fine for a marketing page or an internal tool with a few dozen points. It stops being fine the moment marker volume, search, or control customisation becomes the product, and at that point the work is not configuration but code you own.
Dark mode swaps classes on the wrapper, and the map style is left alone
Theme awareness is listed as automatic adaptation to light and dark mode, and the dependency list shows the mechanism you inherit: next-themes at ^0.4.6 as a runtime dependency, alongside class-variance-authority, clsx, and tailwind-merge, which is the standard shadcn utility set. What that wiring produces is a class swap on a wrapping element. It is not a second set of map styles. Nothing in this repository documents a light style object and a dark style object, a style switch, or any check that the basemap you point at ships a dark variant at all.
The consequence is a mismatch you will have to reconcile yourself. The surrounding interface follows your theme correctly because next-themes drives it, while the map raster continues to render whatever style the tile provider hands back. If your provider offers only a light cartography, you get bright chrome with a bright map inside a dark page, or the reverse, and the fix lives in your application rather than in a prop on these components. The same gap applies to motion: tailwindcss ^4 and tw-animate-css are both present, so an animation layer exists, but no transition or duration defaults for marker, popup, or tooltip appearance are documented. Expect a theme toggle to feel abrupt on map chrome, and expect to tune those durations yourself rather than inherit them.
No releases, no install command in the repository, only a link to the docs
There is no release history to work from. The repository has no GitHub releases, the only version string in the project is 0.1.0 in package.json, and the last recorded push is dated 6 September 2026, so the code itself is recent even though it is unversioned. What you lose with no tags is a return path. There is no changelog to diff, no upgrade notes, and no earlier version to fall back to when a copied component regresses, which means comparing what lives in your tree against the main branch is a manual, per component job.
Installation is handled the same way. There is no install command in the repository. The route is a link: mapcn.dev/docs for getting started, mapcn.dev/docs/installation for installation, and a link labelled Components pointing at mapcn.dev/docs/basic-map. Contributors are given a concrete flow, though, and it is the one place in the project with runnable commands:
git checkout -b feature/amazing-feature
git commit -m 'Add some amazing feature'
git push origin feature/amazing-featureThat sequence forks, branches, commits, pushes, and opens a pull request, and the project invites contributions through it. For a reader, the practical consequence is that adopting these components means copying code you are then responsible for updating, with no tagged version to diff against and the pull request route as the only review path the project names.
Editorial conclusion
mapcn fits a React application that already leans on shadcn and needs a map surface with markers, popups, drawn geometry, and the four standard controls. Adopt it with clear eyes about the division of labour: you supply tile credentials and their licensing, route geometry, any geocoding, marker strategy at scale, and manual updates to the code you copied, because the repository has no tagged releases to fall back on. Before shipping anything commercial, settle the basemap terms first, since that is the one decision this project explicitly refuses to make for you and the only one that can turn a free component set into a bill.
Frequently asked questions
Is mapcn free?
Free for the code: the project is MIT licensed and describes itself as free and open source. The default basemap is a separate matter, since CARTO Basemaps require a CARTO Enterprise license for commercial use and are free only for CARTO grantees under their basemap terms.
Can I use OpenStreetMap for free?
The project names OpenStreetMap tiles as an alternative to CARTO Basemaps, alongside any other MapLibre compatible provider such as MapTiler or Stadia Maps. It does not restate the OpenStreetMap tile usage policy or document how to make the switch, so check the provider terms yourself before pointing production traffic at them.
What does a .map file do?
Nothing in this repository defines a .map file, and no such file appears among the project entries. The only map named path the README points at is the link labelled Components, which leads to mapcn.dev/docs/basic-map.
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/anmolsaini16-mapcn)