freestiler: Vector Tile Generator
Overview
freestiler converts spatial data into PMTiles vector tilesets. Rust-powered tool for creating .pmtiles from sf objects, files, or DuckDB SQL.
References
Read references/API.md before writing code.
references/API.md - Complete function reference with all parameters
references/getting-started.md - Usage patterns and parameter examples
references/zoom-strategy.md - Zoom level guidance by geometry type
references/workflows.md - Complete workflows and integration patterns
references/mapping.md - Visualization and server configuration
When to Use
Use when:
- Dataset >10k features (too large for direct mapgl)
- Need static hosting
- Dataset exceeds memory
Don't use:
- <10k features - pass sf to mapgl directly
- Quick exploration - use
maplibre_view()
- Existing tile pipeline works
Quick Reference
| Function |
Use Case |
Key Params |
freestile() |
Tile sf objects |
input, output, layer_name, min_zoom, max_zoom, base_zoom (opt), drop_rate (opt), tile_format (opt) |
freestile_query() |
Tile from SQL (streaming) |
query, output, layer_name, min_zoom, max_zoom, streaming = "always" |
freestile_file() |
Tile without loading |
input, output, layer_name, min_zoom, max_zoom, engine |
view_tiles() |
Quick visualization |
input, layer_type, color |
serve_tiles() |
Start local server |
path, port |
Quick Start
library(freestiler)
library(sf)
# Basic workflow - counties use max_zoom = 10
nc <- st_read(system.file("shape/nc.shp", package = "sf"))
freestile(input = nc, output = "nc.pmtiles", layer_name = "counties", max_zoom = 10)
view_tiles("nc.pmtiles") # Auto-starts server + opens map
# Large datasets: streaming
freestile_query(query = "SELECT * FROM read_parquet('huge.parquet')",
output = "points.pmtiles", layer_name = "locations",
streaming = "always") # Critical for 10M+ points
# Direct file (no loading to memory)
freestile_file(input = "data.gpkg", output = "output.pmtiles",
layer_name = "features")
Visualization
view_tiles() (Easiest): view_tiles("nc.pmtiles")
Manual Server + mapgl:
serve_tiles("tiles/")
maplibre() |>
add_pmtiles_source(id = "src", url = "http://localhost:8080/data.pmtiles") |>
add_fill_layer(source = "src", source_layer = "layer1")
Direct file://: Requires absolute path in add_pmtiles_source(url = "file://W:/...")
Common Mistakes
- Parameter names: Use
input, output, layer_name (NOT data, tileset, layer)
- Source layer must match:
layer_name in freestile() must match source_layer in mapgl
- CRS must be WGS84: Use
st_transform(4326) before tiling
- Large sf objects: Use
freestile_file() or freestile_query() to avoid loading into memory
- Massive points (10M+): Add
streaming = "always" to freestile_query()
- Tile format: MLT (default, smaller files) vs MVT (broader compatibility, use for Python)
- Large tilesets (>500MB):
serve_tiles() struggles with byte-range requests; launch npx http-server from R via processx::process$new() instead. See references/mapping.md "Serving Large Tilesets" for a ready-made helper function.
When NOT to Use
- Small datasets (<10k features) - pass sf directly to mapgl
- Quick exploration - use
maplibre_view() from mapgl
- Existing tile pipeline already works
Advanced
See references/ for:
- API.md: Complete function reference
- getting-started.md, mapping.md: CRAN vignettes
- Workflows, zoom strategy, SQL patterns, performance tips
Test with validator: Use lib/r-validators/plot-validator.R to verify map output in tests
Resources: Docs | GitHub | See r-mapgl skill
1---2name: r-freestiler3description: Use when code loads or uses freestiler, working with .pmtiles files, creating or serving PMTiles vector tilesets in R, or preparing spatial data for mapgl/MapLibre visualization4---56# freestiler: Vector Tile Generator78## Overview910**freestiler converts spatial data into PMTiles vector tilesets.** Rust-powered tool for creating `.pmtiles` from sf objects, files, or DuckDB SQL.1112## References1314Read `references/API.md` before writing code.1516- `references/API.md` - Complete function reference with all parameters17- `references/getting-started.md` - Usage patterns and parameter examples18- `references/zoom-strategy.md` - Zoom level guidance by geometry type19- `references/workflows.md` - Complete workflows and integration patterns20- `references/mapping.md` - Visualization and server configuration2122## When to Use2324**Use when:**2526- Dataset >10k features (too large for direct mapgl)27- Need static hosting28- Dataset exceeds memory2930**Don't use:**3132- <10k features - pass sf to mapgl directly33- Quick exploration - use `maplibre_view()`34- Existing tile pipeline works3536## Quick Reference3738| Function | Use Case | Key Params |39| ------------------- | ------------------------- | ------------------------------------------------------------------------------------------------------------------ |40| `freestile()` | Tile sf objects | `input`, `output`, `layer_name`, `min_zoom`, `max_zoom`, `base_zoom` (opt), `drop_rate` (opt), `tile_format` (opt) |41| `freestile_query()` | Tile from SQL (streaming) | `query`, `output`, `layer_name`, `min_zoom`, `max_zoom`, `streaming = "always"` |42| `freestile_file()` | Tile without loading | `input`, `output`, `layer_name`, `min_zoom`, `max_zoom`, `engine` |43| `view_tiles()` | Quick visualization | `input`, `layer_type`, `color` |44| `serve_tiles()` | Start local server | `path`, `port` |4546## Quick Start4748```r49library(freestiler)50library(sf)5152# Basic workflow - counties use max_zoom = 1053nc <- st_read(system.file("shape/nc.shp", package = "sf"))54freestile(input = nc, output = "nc.pmtiles", layer_name = "counties", max_zoom = 10)55view_tiles("nc.pmtiles") # Auto-starts server + opens map5657# Large datasets: streaming58freestile_query(query = "SELECT * FROM read_parquet('huge.parquet')",59 output = "points.pmtiles", layer_name = "locations",60 streaming = "always") # Critical for 10M+ points6162# Direct file (no loading to memory)63freestile_file(input = "data.gpkg", output = "output.pmtiles",64 layer_name = "features")65```6667## Visualization6869**view_tiles() (Easiest)**: `view_tiles("nc.pmtiles")`7071**Manual Server + mapgl**:7273```r74serve_tiles("tiles/")75maplibre() |>76 add_pmtiles_source(id = "src", url = "http://localhost:8080/data.pmtiles") |>77 add_fill_layer(source = "src", source_layer = "layer1")78```7980**Direct file://**: Requires absolute path in `add_pmtiles_source(url = "file://W:/...")`8182## Common Mistakes83841. **Parameter names:** Use `input`, `output`, `layer_name` (NOT `data`, `tileset`, `layer`)852. **Source layer must match:** `layer_name` in `freestile()` must match `source_layer` in mapgl863. **CRS must be WGS84:** Use `st_transform(4326)` before tiling874. **Large sf objects:** Use `freestile_file()` or `freestile_query()` to avoid loading into memory885. **Massive points (10M+):** Add `streaming = "always"` to `freestile_query()`896. **Tile format:** MLT (default, smaller files) vs MVT (broader compatibility, use for Python)907. **Large tilesets (>500MB):** `serve_tiles()` struggles with byte-range requests; launch `npx http-server` from R via `processx::process$new()` instead. See `references/mapping.md` "Serving Large Tilesets" for a ready-made helper function.9192## When NOT to Use9394- Small datasets (<10k features) - pass sf directly to mapgl95- Quick exploration - use `maplibre_view()` from mapgl96- Existing tile pipeline already works9798## Advanced99100See `references/` for:101102- **API.md**: Complete function reference103- **getting-started.md**, **mapping.md**: CRAN vignettes104- Workflows, zoom strategy, SQL patterns, performance tips105106**Test with validator:** Use `lib/r-validators/plot-validator.R` to verify map output in tests107108**Resources:** [Docs](https://walker-data.com/freestiler/) | [GitHub](https://github.com/walkerke/freestiler/) | See `r-mapgl` skill