crowd-bloom-720p-small.mp4
Native Swift + Metal map rendering engine for SwiftUI apps.
ImmersiveMap is a native Swift + Metal map rendering engine for SwiftUI apps on Apple platforms. Pure Swift and Metal, with no native SDK wrapped in a Swift API.
It is built for apps where the map is the product rather than decoration: live location and social maps, games, travel, logistics, data visualisation. You get direct control over rendering, your own vector tile data, globe rendering, and an engine you can read and extend.
- Swift 6.0+
- Xcode 16+
- iOS 18+
- macOS 15+ (native AppKit, not Mac Catalyst)
- Metal-capable device or simulator
ImmersiveMap is available on the Swift Package Index.
Add ImmersiveMap as a Swift Package dependency:
https://github.com/artembobkin/ImmersiveMap.git
Or in Xcode:
- Open your project.
- Select File → Add Package Dependencies…
- Paste the repository URL.
- Add the
ImmersiveMaplibrary to your app target.
import SwiftUI
import ImmersiveMap
struct ContentView: View {
@State private var camera = ImmersiveMapCameraController()
var body: some View {
ImmersiveMapView()
.cameraController(camera)
.enableCameraUIControls()
.ignoresSafeArea()
}
}ImmersiveMap ships with a built-in tile provider, so the snippet above renders a map out of the box - no token or account required (see Where the map data comes from). The same SwiftUI code runs natively on iOS (UIKit host) and macOS (AppKit host): ImmersiveMapView bridges to the platform view internally.
Any other MVT source plugs in with one URL template, .tileURLTemplate("https://tiles.com/{x}/{y}/{z}?apiKey=xxx"), see the custom tile source guide.
| Feature | Status |
|---|---|
| SwiftUI integration | Available |
| Native iOS (UIKit host) | Available |
| Native macOS (AppKit host, no Catalyst) | Available |
| Native Metal renderer | Available |
| Built-in vector tiles, no token required | Available |
| Your own MVT tile source | Available |
| Customizable attribution badge | Available |
| Globe rendering and globe-to-flat morph | Available |
| Labels with MSDF text and GPU collision | Available |
| Map styling and colors | Available |
| Extruded buildings and shadows | Available |
| Sun, day/night terminator, atmosphere, starfield and transparent space | Available |
| SwiftUI markers | Available |
| Avatars / live markers | Available |
| Tap selection of avatars and models | Available |
| Routes on the globe | Available |
| 3D scene models | Available |
| Camera flights and scripted tours | Available |
| Camera travelling along a path | Available |
| Tour video export | Available |
| Disk / memory tile cache | Available |
| Offline regions: download once, render without a network | Available |
| Render loop, view reuse and debug HUD | Available |
Measured from a Release archive of the iOS demo app (Examples/ImmersiveMapIOS, arm64, unsigned). That demo is about twenty lines of SwiftUI, so these numbers are effectively what the engine itself adds to an app.
| Part | Size |
|---|---|
| App bundle, total | 6.7 MB |
| Binary (engine, SwiftProtobuf) | 3.9 MB |
| Resources | 2.8 MB |
| ├ MSDF font atlases, two weights | 2.2 MB |
| ├ Compiled Metal library | 276 KB |
| └ Glyph metrics | 192 KB |
Most of the resource weight is the bundled Noto Sans MSDF atlases that draw every label on the map. If your app only needs a subset of scripts, regenerate smaller atlases with Tools/TextAtlas/generate_text_atlas.sh.
The App Store download size is lower than the archive size, since the store compresses and thins the bundle.
The Examples folder holds small host apps that show the engine's features in practice: camera tours and video export, markers, avatars, routes, 3D scene models, live settings, offline regions, and a custom tile source. Clone the repository, open ImmersiveMap.xcworkspace, pick an example scheme, and run: they reference the package locally, and every one but the custom tile source renders the built-in tile provider with no token or account.
immersivemap.dev is the home of this project. It runs the vector tile service the engine renders by default, and hosts the account dashboard where you create API keys and watch your tile usage.
Nothing there is required to get started: the default provider renders out of the box with no token and no account, on a shared public pool. A free key from immersivemap.dev/account moves you off that shared pool onto your own throughput, with usage visible in the dashboard.
The map shows a small attribution badge ("© OpenStreetMap © OpenMapTiles" with the built-in tiles) because map data licenses require visible credit. The badge is restylable (size, position, text color) and can be replaced with your own credit elsewhere in the app. The details, including what exactly has to be credited, where it has to appear, and what stays your app's responsibility, are in ATTRIBUTION.md.
Crediting ImmersiveMap itself is not required: the license is MIT and nothing here changes that. But if the engine is useful in your app, a line like this on an about or credits screen is genuinely appreciated:
Maps powered by ImmersiveMap (immersivemap.dev)
And if you ship something built with ImmersiveMap, say hello in Discussions. Knowing where the engine ends up is what keeps it moving.
- Apple platforms only. Requires Metal.
- App size is measured (see App size), frame time and memory numbers are not published yet.
- Maintained by one person. Issues and integration questions are answered quickly, but plan accordingly.
ImmersiveMap is currently maintained as a single-maintainer project. Issues and feedback are welcome. Pull requests are accepted for documentation, examples, bug fixes, and tests. See CONTRIBUTING.md.
Bug reports and feature requests belong in Issues. Questions, ideas, and anything open-ended belong in Discussions.
ImmersiveMap is available under the MIT license. See LICENSE. The internal earcut triangulator is a port of ISC-licensed Mapbox code; its notice, ready to copy into an app's acknowledgements screen, is in THIRD-PARTY-NOTICES.md.
I am available for consulting and custom ImmersiveMap integrations.
To get in touch, start a discussion, or write to me in the chat at immersivemap.dev/account.

