Why Offline Matters
Digital access fails marginalized communities:
- Remote border areas lack cellular coverage
- Detention facilities block internet access
- Enforcement situations prevent phone use
- Economic barriers limit data plans
Physical and offline maps are critical infrastructure.
Print Map Generation
The Challenge
Web maps use low-DPI tile streams optimized for screens, not print quality.
| Medium | Resolution |
|---|---|
| Screen | 72-96 DPI |
| 300 DPI |
Client-Side Export
import html2canvas from 'html2canvas';
async function exportMap(format = 'png') {
// Temporarily increase tile quality
map.options.zoomSnap = 0;
const canvas = await html2canvas(
document.getElementById('map'),
{
scale: 4, // 4x resolution
useCORS: true,
allowTaint: false
}
);
// Download
const link = document.createElement('a');
link.download = `checkpoint-map-${Date.now()}.${format}`;
link.href = canvas.toDataURL(`image/${format}`);
link.click();
}
Print Stylesheet
@media print {
/* Hide UI controls */
.leaflet-control-zoom,
.leaflet-control-layers,
.map-controls {
display: none !important;
}
/* Maximize map */
#map {
width: 100%;
height: 100vh;
}
/* High contrast markers */
.leaflet-marker-icon {
filter: contrast(1.2);
}
/* Add attribution */
.print-attribution {
display: block;
position: fixed;
bottom: 10px;
font-size: 8pt;
}
}
Print Button UI
<div class="print-controls">
<button onclick="window.print()">
Print Current View
</button>
<button onclick="exportMap('png')">
Download as Image
</button>
<button onclick="exportMap('pdf')">
Download as PDF
</button>
</div>
Static Map Images
For Print Materials
Generate static images without JavaScript:
<!-- Using OpenStreetMap static tiles -->
<img src="https://staticmap.openstreetmap.de/staticmap.php
?center=32.7,-117.1
&zoom=10
&size=800x600
&markers=32.7,-117.1,red"
alt="Map of San Diego checkpoint locations">
MapToPoster Approach
For high-quality static exports:
const poster = new MapToPoster(map, {
width: 3300, // 11" at 300dpi
height: 2550, // 8.5" at 300dpi
format: 'png',
title: 'Immigration Checkpoints',
attribution: '© OpenStreetMap contributors'
});
poster.generate().then(dataUrl => {
downloadImage(dataUrl, 'checkpoint-poster.png');
});
Offline Mobile Maps
OsmAnd Configuration
OsmAnd is a free, offline-first navigation app.
Download: Android/iOS app stores
Custom POI Import
<?xml version="1.0" encoding="UTF-8"?>
<gpx version="1.1" creator="advocacy-tools">
<metadata>
<name>Immigration Checkpoints</name>
<desc>Known checkpoint locations</desc>
<time>2026-03-25T00:00:00Z</time>
</metadata>
<wpt lat="32.9012" lon="-116.8234">
<name>I-8 Checkpoint (East)</name>
<desc>Permanent. All traffic stopped. Open 24/7.</desc>
<type>checkpoint</type>
<extensions>
<osmand:icon>special_trekking</osmand:icon>
<osmand:background>circle</osmand:background>
<osmand:color>#FF0000</osmand:color>
</extensions>
</wpt>
<wpt lat="33.0234" lon="-117.1234">
<name>Legal Aid - San Diego</name>
<desc>Free immigration legal services. Spanish available.</desc>
<type>legal_aid</type>
<extensions>
<osmand:icon>amenity_courthouse</osmand:icon>
<osmand:background>square</osmand:background>
<osmand:color>#00FF00</osmand:color>
</extensions>
</wpt>
</gpx>
Installing in OsmAnd
- Transfer
.gpxfile to device - Open OsmAnd → Menu → My Places
- Tap + → Import
- Select GPX file
- Points appear on map
MBTiles for Offline Basemaps
What Are MBTiles?
SQLite database containing pre-rendered map tiles for offline use.
Generating MBTiles
# Using tippecanoe
tippecanoe -o region.mbtiles \
--minimum-zoom=6 \
--maximum-zoom=14 \
facilities.geojson \
checkpoints.geojson
# Using tilemaker
tilemaker --input region.osm.pbf \
--output region.mbtiles \
--config config.json
Serving Offline
For mobile apps that support MBTiles:
| App | MBTiles Support |
|---|---|
| OsmAnd | Import as overlay |
| Locus Map | Native support |
| AlpineQuest | Native support |
| Avenza Maps | Import support |
QR Code Integration
Linking Print to Digital
<!-- On printed flyer -->
<div class="qr-section">
<img src="/qr/offline-map-package.png"
alt="Scan to download offline maps">
<p>Scan to download offline checkpoint map</p>
</div>
Generating QR Codes
import QRCode from 'qrcode';
async function generateQR(url, filename) {
const dataUrl = await QRCode.toDataURL(url, {
width: 200,
margin: 2,
color: {
dark: '#000000',
light: '#FFFFFF'
}
});
return dataUrl;
}
// Generate for offline package
const qr = await generateQR(
'https://advocacy.org/downloads/checkpoint-map.gpx',
'checkpoint-qr.png'
);
Print Material Design
.print-card {
width: 3.5in;
height: 2in;
padding: 0.25in;
display: flex;
}
.print-card .qr-code {
width: 1.5in;
height: 1.5in;
}
.print-card .instructions {
flex: 1;
font-size: 10pt;
line-height: 1.3;
}
Distribution Methods
Physical Distribution
| Location | Method |
|---|---|
| Community centers | Printed cards |
| Legal clinics | Flyer stacks |
| Churches | Bulletin inserts |
| Schools | Parent packets |
| Community events | Handouts |
Digital Distribution
| Method | Use Case |
|---|---|
| Website download | Self-service |
| QR code scan | Print-to-digital |
| WhatsApp/Signal | Direct sharing |
| USB drives | Community events |
File Size Considerations
Offline Package Sizes
| Content | Approximate Size |
|---|---|
| GPX with 100 POIs | 50 KB |
| County MBTiles | 50-200 MB |
| State MBTiles | 500 MB - 2 GB |
| Region (zoom 6-14) | 100-500 MB |
Optimization Strategies
| Strategy | Reduction |
|---|---|
| Limit zoom levels | 50-70% |
| Reduce tile area | Proportional |
| Compress tiles | 20-30% |
| Vector vs raster | 50-80% |
Keeping Offline Data Current
Version Control
{
"package_name": "checkpoint-map",
"version": "2026.03.25",
"last_updated": "2026-03-25T00:00:00Z",
"checksum": "sha256:abc123...",
"download_url": "/downloads/checkpoints-2026-03-25.gpx"
}
Update Notification
// Check for updates on app open
async function checkForUpdates() {
const current = localStorage.getItem('package_version');
const response = await fetch('/api/package-info');
const latest = await response.json();
if (latest.version !== current) {
showUpdatePrompt(latest);
}
}
Printable Companions
Legend Cards
Print-ready legend for map interpretation:
<div class="print-legend">
<h3>Map Legend</h3>
<ul>
<li><span class="marker red">●</span> Permanent Checkpoint</li>
<li><span class="marker orange">●</span> Known Roving Area</li>
<li><span class="marker green">●</span> Legal Aid Office</li>
<li><span class="marker blue">●</span> Sanctuary Zone</li>
</ul>
<p class="note">Data as of March 2026</p>
</div>
Emergency Contact Cards
Include with map distributions:
<div class="contact-card">
<h4>If Stopped by Immigration</h4>
<ul>
<li>Stay calm</li>
<li>You have the right to remain silent</li>
<li>Don't sign anything</li>
</ul>
<p><strong>Legal Hotline:</strong> 1-800-XXX-XXXX</p>
</div>
Related Resources
- Tile Servers - Offline tile generation
- QGIS - Data preparation for print
- Privacy - Offline protects privacy
- Printable Resources - Ready-to-print materials