Configuration Reference
Complete reference for all map.config.ts options.
For environment variables, see the Environment Variables Reference. For upgrade guidance, see the Migration Guide.
MapConfig
The root configuration object.
interface MapConfig {
branding: BrandingConfig;
dataSources: DataSourceConfig[];
map: MapViewConfig;
controls: ControlsConfig;
theme: ThemeConfig;
labels?: LabelsConfig;
filterVisibility?: FilterVisibilityConfig;
features?: FeaturesConfig;
loader?: LoaderConfig;
}BrandingConfig
interface BrandingConfig {
/** Display name in header and meta tags */
name: string;
/** Short description for meta tags */
description: string;
/** Path to logo image */
logo?: string;
/** Path to favicon (relative to public/) */
favicon?: string;
/** Path to Open Graph image (1200x630px recommended) */
ogImage?: string;
/** Primary brand color (hex) */
primaryColor?: string;
/** Social media links */
social?: {
twitter?: string;
github?: string;
website?: string;
};
}DataSourceConfig
interface DataSourceConfig {
/** Unique identifier */
id: string;
/** Display name in UI */
name: string;
/** Optional description */
description?: string;
/** Hex color for markers from this source */
color: string;
/** Optional icon identifier */
icon?: string;
/** Adapter type */
adapter: 'static' | 'supabase' | 'api';
/** Adapter-specific configuration */
adapterConfig: StaticAdapterConfig | SupabaseAdapterConfig | ApiAdapterConfig;
/** Whether this source is currently enabled */
enabled: boolean;
/** Filter visibility settings for this use case */
filterVisibility?: FilterVisibilityConfig;
}StaticAdapterConfig
interface StaticAdapterConfig {
/** Path to JSON file in public/ */
path: string;
/** Request timeout in milliseconds (default: 30000) */
timeoutMs?: number;
/** Maximum response size in bytes (default: 10MB) */
maxResponseSize?: number;
/** Enable Zod schema validation (default: false) */
validateData?: boolean;
/** Cache TTL in milliseconds (default: 300000 / 5 minutes) */
cacheTtlMs?: number;
}SupabaseAdapterConfig
interface SupabaseAdapterConfig {
/** Custom Supabase URL (overrides env var) */
url?: string;
/** Custom anon key (overrides env var) */
anonKey?: string;
/** Request timeout in milliseconds (default: 30000) */
timeoutMs?: number;
/** Maximum response size in bytes (default: 10MB) */
maxResponseSize?: number;
/** Enable Zod schema validation (default: false) */
validateData?: boolean;
/** Enable response caching (default: true) */
enableCache?: boolean;
/** Cache TTL in milliseconds (default: 300000 / 5 minutes) */
cacheTtlMs?: number;
}ApiAdapterConfig
interface ApiAdapterConfig {
/** API endpoint URL (must be HTTPS in production) */
endpoint: string;
/** API key for Bearer token authentication */
apiKey?: string;
/** Custom headers to include with requests */
headers?: Record<string, string>;
/** Request timeout in milliseconds (default: 30000) */
timeoutMs?: number;
/** Maximum response size in bytes (default: 10MB) */
maxResponseSize?: number;
/** Allow HTTP for localhost development (default: true in dev) */
allowInsecureLocalhost?: boolean;
/** Enforce HTTPS (default: true in production) */
enforceHttps?: boolean;
/** Enable Zod schema validation (default: false) */
validateData?: boolean;
/** Enable response caching (default: true) */
enableCache?: boolean;
/** Cache TTL in milliseconds (default: 300000 / 5 minutes) */
cacheTtlMs?: number;
}Security Features: All adapters include built-in security measures:
- HTTPS enforcement in production
- SSRF protection (blocks requests to private IPs and metadata endpoints)
- Rate limiting (60 requests/minute per adapter)
- Response size limits (10MB default)
- Path traversal prevention
- Error message sanitization
FilterVisibilityConfig
interface FilterVisibilityConfig {
/** Show quick filter toggles */
showQuickFilters?: boolean;
/** Classification filters */
showIncidentType?: boolean;
showHynekClassification?: boolean;
showValleeClassification?: boolean;
showExplanationStatus?: boolean;
/** Evidence filters */
showDetectionMethods?: boolean;
showEvidenceTypes?: boolean;
/** Investigation filters */
showInvestigationStatus?: boolean;
showInvestigatingBodies?: boolean;
/** Object filters */
showObjectShapes?: boolean;
/** Location filters */
showLocationSensitivity?: boolean;
showCountry?: boolean;
showSiteType?: boolean;
}MapViewConfig
interface MapViewConfig {
/** Initial center [longitude, latitude] */
center: [number, number];
/** Initial zoom level */
zoom: number;
/** Mapbox style URL (used when theme styles not specified) */
style: string;
/** Mapbox style URL for light mode */
lightStyle?: string;
/** Mapbox style URL for dark mode */
darkStyle?: string;
/** Minimum zoom level */
minZoom?: number;
/** Maximum zoom level */
maxZoom?: number;
/** Clustering configuration */
clustering?: ClusteringConfig;
}ClusteringConfig
interface ClusteringConfig {
/** Clustering mode */
mode: 'mapbox' | 'react' | 'none';
/** Cluster radius in pixels */
radius?: number;
/** Max zoom for clustering */
maxZoom?: number;
/** Mapbox-specific styling */
mapboxStyle?: {
colors: {
small: string; // < 10 points
medium: string; // 10-100 points
large: string; // > 100 points
};
sizes: {
small: number;
medium: number;
large: number;
};
textColor?: string;
textSize?: number;
strokeColor?: string;
strokeWidth?: number;
};
}ControlsConfig
interface ControlsConfig {
timeline?: ControlConfig;
filters?: ControlConfig;
stats?: ControlConfig;
search?: ControlConfig;
legend?: ControlConfig;
sourceToggle?: ControlConfig;
incidentFeed?: IncidentFeedConfig;
}
interface ControlConfig {
enabled: boolean;
position?: ControlPosition;
options?: Record<string, unknown>;
}
type ControlPosition =
| 'sidebar'
| 'bottom'
| 'top-left'
| 'top-right'
| 'bottom-left'
| 'bottom-right';IncidentFeedConfig
interface IncidentFeedConfig extends ControlConfig {
/** Number of items to load initially */
initialCount?: number;
/** Number of items to load on scroll */
pageSize?: number;
/** Sort order for feed */
sortBy?: 'date' | 'sensitivity' | 'location';
/** Sort direction */
sortDirection?: 'asc' | 'desc';
}ThemeConfig
interface ThemeConfig {
/** Default theme mode */
defaultTheme: 'light' | 'dark' | 'system';
/** Allow users to toggle theme */
allowToggle: boolean;
/** Show theme toggle in UI */
showToggle: boolean;
/** Toggle position */
togglePosition?: 'top-left' | 'top-right' | 'bottom-left' | 'bottom-right';
}LabelsConfig
Configurable UI labels for customizing terminology. All labels are optional with sensible defaults.
interface LabelsConfig {
// Sidebar titles
/** Title for the filter sidebar (default: "Filters") */
filterSidebarTitle?: string;
/** Title for the incident feed (default: "Incidents") */
incidentFeedTitle?: string;
// Section titles
/** Title for quick filters section (default: "Quick Filters") */
quickFiltersTitle?: string;
/** Title for location sensitivity filter (default: "Location Sensitivity") */
locationSensitivityTitle?: string;
/** Title for incident type filter (default: "Incident Type") */
incidentTypeTitle?: string;
/** Title for site type filter (default: "Site Type") */
siteTypeTitle?: string;
/** Title for country filter (default: "Country") */
countryTitle?: string;
// Empty states
/** Title when no incidents found (default: "No incidents found") */
emptyStateTitle?: string;
/** Message when no incidents found */
emptyStateMessage?: string;
// Stats labels
/** Label for total incidents count (default: "Total Incidents") */
totalIncidentsLabel?: string;
/** Label for filtered incidents count (default: "Filtered") */
filteredIncidentsLabel?: string;
/** Label for date range display (default: "Date Range") */
dateRangeLabel?: string;
// Item labels (singular/plural for incident terminology)
/** Singular term for incident (default: "incident") */
incidentSingular?: string;
/** Plural term for incident (default: "incidents") */
incidentPlural?: string;
/** Term for "report" as alternative (default: "report") */
reportSingular?: string;
/** Plural term for report (default: "reports") */
reportPlural?: string;
}FeaturesConfig
interface FeaturesConfig {
/** Allow users to add custom data sources at runtime */
allowCustomSources?: boolean;
/** Show data source attribution */
showAttribution?: boolean;
/** Enable keyboard shortcuts */
keyboardShortcuts?: boolean;
}LoaderConfig
Configuration for the app initialization loader. Controls the appearance and behavior of the loading screen shown while data and map are initializing.
interface LoaderConfig {
/** Animation variant for the loader (default: 'orbit') */
variant?: 'spinner' | 'dots' | 'orbit' | 'pulse' | 'bars';
/** Size of the loader (default: 'lg') */
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl';
/** Customizable loading messages */
messages?: {
/** Message shown during app initialization (default: 'Initializing...') */
initializing?: string;
};
/** Duration of the fade-out transition in milliseconds (default: 500) */
transitionDuration?: number;
}Loader Variants
| Variant | Description |
|---|---|
spinner | Gradient arc that rotates with a fade trail |
dots | Three dots that pulse in sequence |
orbit | Single dot orbiting around a track ring (default) |
pulse | Expanding concentric rings |
bars | Equalizer-style bars that animate up/down |
Example
// map.config.ts
const config: Partial<MapConfig> = {
loader: {
variant: 'dots',
size: 'lg',
messages: {
initializing: 'Loading your map...',
},
transitionDuration: 400,
},
};The loader displays a unified loading state for both data fetching and map initialization. The app content fades in smoothly once both are complete.
Default Values
const defaults: MapConfig = {
branding: {
name: 'Incident Map',
description: 'Track and visualize geospatial incidents',
favicon: '/favicon.ico',
ogImage: '/og-image.png',
},
dataSources: [
{
id: 'demo',
name: 'Demo Data',
description: 'Sample incident data for demonstration',
color: '#3b82f6',
adapter: 'static',
adapterConfig: { path: '/data/demo.json' },
enabled: true,
},
],
map: {
center: [-98.5795, 39.8283], // US center
zoom: 4,
style: 'mapbox://styles/mapbox/dark-v11',
lightStyle: 'mapbox://styles/mapbox/light-v11',
darkStyle: 'mapbox://styles/mapbox/dark-v11',
minZoom: 2,
maxZoom: 18,
clustering: {
mode: 'mapbox',
radius: 50,
maxZoom: 14,
mapboxStyle: {
colors: {
small: '#3b82f6',
medium: '#f97316',
large: '#ef4444',
},
sizes: {
small: 20,
medium: 30,
large: 40,
},
textColor: '#ffffff',
textSize: 12,
},
},
},
controls: {
timeline: { enabled: true, position: 'bottom' },
filters: { enabled: true, position: 'sidebar' },
stats: { enabled: true, position: 'top-right' },
sourceToggle: { enabled: true, position: 'sidebar' },
search: { enabled: false },
legend: { enabled: true, position: 'bottom-right' },
incidentFeed: {
enabled: false,
position: 'sidebar',
initialCount: 20,
pageSize: 10,
sortBy: 'date',
sortDirection: 'desc',
},
},
theme: {
defaultTheme: 'system',
allowToggle: true,
showToggle: true,
togglePosition: 'top-right',
},
filterVisibility: {
showQuickFilters: true,
showLocationSensitivity: true,
showIncidentType: true,
showHynekClassification: true,
showExplanationStatus: true,
showCountry: true,
showSiteType: true,
},
features: {
allowCustomSources: false,
showAttribution: true,
keyboardShortcuts: true,
},
loader: {
variant: 'orbit',
size: 'lg',
messages: {
initializing: 'Initializing...',
},
transitionDuration: 500,
},
};Related
- Environment Variables — All env vars
- Data Sources Guide — Detailed adapter setup
- Customization Guide — Branding and theming
- Examples & Recipes — Real-world configurations
- Changelog — Version history
- Migration Guide — Upgrade between versions