# silversonicaxel/maplibre-layer-factory architecture

> Architecture diagram of the GitHub repository silversonicaxel/maplibre-layer-factory, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-06-16). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/silversonicaxel/maplibre-layer-factory
- Repository: https://github.com/silversonicaxel/maplibre-layer-factory

## Overview

1. **What this repository is**
   - `maplibre-layer-factory` is a **TypeScript UI plugin for MapLibre GL JS**. It is not a standalone app or backend service; it is a **control library** that gets mounted into an existing MapLibre map via `map.addControl(...)`.

2. **Top-level shape of the repo**
   - The repository is very small and library-focused: one source entrypoint in `src/index.ts`, one stylesheet in `src/index.css`, and a Vite setup (`vite.config.ts`) for building/distributing the package.
   - `index.html` is likely a local demo/dev entry used by Vite, not a production surface.

3. **Primary runtime boundary**
   - The library lives entirely on the **browser side** and depends on the **MapLibre GL JS runtime**.
   - Its main integration boundary is the MapLibre control API: it receives a map instance from the host app and renders a custom control into the map UI.

4. **Core responsibility**
   - The library’s job is to **inspect layer metadata and render a selector UI** that toggles layer visibility.
   - It abstracts the complexity of layer switching into a reusable “factory” control, rather than forcing the app to build a custom legend or layer switcher.

5. **Main UI subsystems**
   - The README describes a control structure with:
     - a **container**
     - a **toggle**
     - a **panel**
     - panel sections for **layers**, **label**, and **overlays**
   - This suggests the entrypoint builds a composite control with both a collapsed/expanded state and separate rendering paths for different layer types.

6. **Layer classification flow**
   - Each layer is driven by a metadata object with fields like `name`, `caption`, `placeholder`, `ignore`, `overlay`, and `group`.
   - The control likely partitions incoming layers into:
     - **base layers**: single-select, rendered as squared buttons
     - **overlay layers**: multi-select, rendered as checkboxes
     - **ignored layers**: excluded from the UI entirely
   - Overlays can also be grouped under collapsible accordion sections.

7. **Configuration and styling flow**
   - The factory accepts a single options object with:
     - **orientation** for layout
     - **panel and button styles**
     - **label styles**
     - **overlay styles**
     - a `withLabel` flag
   - Styling is intentionally split into granular style slots, which implies the control assembles DOM elements and applies inline style objects or style mappings per region/state.

8. **State and interaction model**
   - The control likely maintains local UI state for:
     - panel open/closed state
     - currently selected base layer
     - overlay checkbox states
     - accordion open/closed state for overlay groups
   - Interaction is centered on showing/hiding MapLibre layers, so the control acts as the state bridge between the DOM and the map style layer visibility.

9. **Asset and presentation layer**
   - `src/index.css` is a dedicated styling layer, meaning the package ships a **base visual skin** in addition to runtime-generated styles.
   - Consumers are expected to import that CSS alongside the library, so the architecture separates **default presentation** from **runtime customization**.

10. **Build/distribution architecture**
   - The presence of `package.json`, `package-lock.json`, `tsconfig.json`, and `vite.config.ts` indicates a **bundled library distribution** rather than raw source publishing.
   - Vite is the build tool, likely producing a browser-ready package and associated stylesheet for npm consumption.

11. **Consumer integration boundary**
   - The host application is responsible for:
     - creating the MapLibre map
     - supplying layer metadata/configuration
     - importing the library and its CSS
     - mounting the control into a chosen map corner
   - The plugin does not appear to own map creation, layer loading, or data fetching.

12. **Notable architectural characteristic**
   - This is a **single-feature library with a shallow file tree**, so most architecture is concentrated in one entrypoint rather than spread across services or modules.
   - For a diagram, the best representation is: **host app → MapLibre map instance → custom layer factory control → DOM UI + layer visibility updates**.

Main entry points: [`src/index.ts`](https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/src/index.ts) (Classifier), [`src/index.css`](https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/src/index.css) (CSS skin), [`vite.config.ts`](https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/vite.config.ts) (Vite build), [`index.html`](https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/index.html) (Demo page)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_runtime["Runtime/UI"]
  node_host_app["Host app<br/>consumer"]
  node_maplibre_map["MapLibre map<br/>runtime map"]
  node_layer_factory_control["Layer factory<br/>map control<br/>[index.ts]"]
  node_control_shell["Control shell<br/>ui shell<br/>[index.ts]"]
  node_toggle_button(("Toggle<br/>ui button<br/>[index.ts]"))
  node_panel_view["Panel<br/>[index.ts]"]
  node_layer_metadata["Layer metadata<br/>config model"]
  node_layer_classifier{{"Classifier<br/>layer routing<br/>[index.ts]"}}
  node_base_layers["Base layers<br/>single-select<br/>[index.ts]"]
  node_overlay_layers["Overlays<br/>multi-select<br/>[index.ts]"]
  node_overlay_groups["Groups<br/>accordion<br/>[index.ts]"]
  node_label_section["Labels<br/>ui section<br/>[index.ts]"]
  node_visibility_state(("UI state<br/>[index.ts]"))
  node_layer_visibility{{"Layer visibility<br/>map update<br/>[index.ts]"}}
  node_css_skin["CSS skin<br/>stylesheet<br/>[index.css]"]
  node_entry_module["Entry module<br/>module entry<br/>[index.ts]"]
end

subgraph group_build["Build/Distribution"]
  node_vite_build["Vite build<br/>bundler<br/>[vite.config.ts]"]
  node_demo_page["Demo page<br/>dev entry<br/>[index.html]"]
  node_package_manifest["Package<br/>[package.json]"]
end

node_host_app -->|"creates"| node_maplibre_map
node_host_app -->|"imports"| node_entry_module
node_entry_module -->|"exports"| node_layer_factory_control
node_layer_factory_control -->|"builds"| node_control_shell
node_control_shell -->|"contains"| node_toggle_button
node_control_shell -->|"contains"| node_panel_view
node_layer_factory_control -->|"mounts on"| node_maplibre_map
node_layer_metadata -->|"drives"| node_layer_classifier
node_layer_classifier -->|"routes to"| node_base_layers
node_layer_classifier -->|"routes to"| node_overlay_layers
node_layer_classifier -->|"organizes"| node_overlay_groups
node_layer_classifier -->|"optionally adds"| node_label_section
node_toggle_button -->|"toggles"| node_visibility_state
node_panel_view -->|"reads"| node_visibility_state
node_base_layers -->|"updates"| node_layer_visibility
node_overlay_layers -->|"updates"| node_layer_visibility
node_maplibre_map -->|"applies"| node_layer_visibility
node_css_skin -->|"styles"| node_control_shell
node_css_skin -->|"styles"| node_toggle_button
node_css_skin -->|"styles"| node_panel_view
node_vite_build -->|"bundles"| node_entry_module
node_vite_build -->|"bundles"| node_css_skin
node_demo_page -->|"loads"| node_entry_module
node_package_manifest -->|"orchestrates"| node_vite_build

click node_layer_factory_control "https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/src/index.ts"
click node_control_shell "https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/src/index.ts"
click node_toggle_button "https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/src/index.ts"
click node_panel_view "https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/src/index.ts"
click node_layer_classifier "https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/src/index.ts"
click node_base_layers "https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/src/index.ts"
click node_overlay_layers "https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/src/index.ts"
click node_overlay_groups "https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/src/index.ts"
click node_label_section "https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/src/index.ts"
click node_visibility_state "https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/src/index.ts"
click node_layer_visibility "https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/src/index.ts"
click node_css_skin "https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/src/index.css"
click node_entry_module "https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/src/index.ts"
click node_vite_build "https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/vite.config.ts"
click node_demo_page "https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/index.html"
click node_package_manifest "https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/package.json"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_host_app,node_maplibre_map,node_layer_factory_control,node_control_shell,node_toggle_button,node_panel_view,node_layer_metadata,node_layer_classifier,node_base_layers,node_overlay_layers,node_overlay_groups,node_label_section,node_visibility_state,node_layer_visibility,node_css_skin,node_entry_module toneBlue
class node_vite_build,node_demo_page,node_package_manifest toneAmber
```

## Components

### Runtime/UI

Browser-side control mounted into an existing MapLibre map.

- **Host app**: consumer · Creates the map and mounts the control.
- **MapLibre map**: runtime map · The map instance that accepts custom controls.
- [Layer factory](https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/src/index.ts): map control · Main reusable control exported by the library. · `src/index.ts`
- [Control shell](https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/src/index.ts): ui shell · Container that assembles the control regions. · `src/index.ts`
- [Toggle](https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/src/index.ts): ui button · Collapsed/expanded control trigger. · `src/index.ts`
- [Panel](https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/src/index.ts): ui panel · Expanded layer selector panel. · `src/index.ts`
- **Layer metadata**: config model · Per-layer fields such as name, caption, ignore, overlay, and group.
- [Classifier](https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/src/index.ts): layer routing · Splits incoming layers into base, overlay, and ignored sets. · `src/index.ts`
- [Base layers](https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/src/index.ts): single-select · Mutually exclusive layers shown as primary choices. · `src/index.ts`
- [Overlays](https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/src/index.ts): multi-select · Independently toggled layers shown as checkboxes. · `src/index.ts`
- [Groups](https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/src/index.ts): accordion · Optional collapsible grouping for overlay layers. · `src/index.ts`
- [Labels](https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/src/index.ts): ui section · Optional label area controlled by the withLabel option. · `src/index.ts`
- [UI state](https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/src/index.ts): state · Tracks open/closed panel state and current layer selections. · `src/index.ts`
- [Layer visibility](https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/src/index.ts): map update · Applies visibility changes back to MapLibre style layers. · `src/index.ts`
- [CSS skin](https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/src/index.css): stylesheet · Base presentation layer shipped with the package. · `src/index.css`
- [Entry module](https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/src/index.ts): module entry · Public TypeScript entrypoint that wires the control together. · `src/index.ts`

### Build/Distribution

Library bundling, packaging, and local demo entrypoints.

- [Vite build](https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/vite.config.ts): bundler · Produces the distributable browser library. · `vite.config.ts`
- [Demo page](https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/index.html): dev entry · Local Vite HTML entry for development or preview. · `index.html`
- [Package](https://github.com/silversonicaxel/maplibre-layer-factory/blob/main/package.json): npm package · Declares library metadata and scripts. · `package.json`

## Connections

- Host app → MapLibre map: creates · The application owns the map instance.
- Host app → Entry module: imports · The app consumes the library entrypoint.
- Entry module → Layer factory: exports · Public API centers on the custom control.
- Layer factory → Control shell: builds · The control composes the UI shell.
- Control shell → Toggle: contains · The shell renders the collapse/expand trigger.
- Control shell → Panel: contains · The shell renders the selector panel.
- Layer factory → MapLibre map: mounts on · The control is attached through MapLibre's control API.
- Layer metadata → Classifier: drives · Metadata determines how layers are routed.
- Classifier → Base layers: routes to · Non-overlay layers become base choices.
- Classifier → Overlays: routes to · Overlay layers are collected separately.
- Classifier → Groups: organizes · Grouped overlays become accordion sections.
- Classifier → Labels: optionally adds · Label rendering depends on configuration.
- Toggle → UI state: toggles · Open/closed panel state is local UI state.
- Panel → UI state: reads · Panel contents reflect current selection state.
- Base layers → Layer visibility: updates · Selecting a base layer changes map visibility.
- Overlays → Layer visibility: updates · Overlay checkbox state is pushed to the map.
- MapLibre map → Layer visibility: applies · Visibility changes are applied on the map style.
- CSS skin → Control shell: styles · Default skin covers the container and layout.
- CSS skin → Toggle: styles · The base stylesheet styles the control trigger.
- CSS skin → Panel: styles · The base stylesheet styles the panel surfaces.
- Vite build → Entry module: bundles · Vite compiles the TypeScript entry.
- Vite build → CSS skin: bundles · The stylesheet is part of the distributable package.
- Demo page → Entry module: loads · The local HTML entry references the library during dev.
- Package → Vite build: orchestrates · Package scripts and metadata drive the build.
