Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Ploots-click

A static web chart builder for publication-ready figures. and export a print-quality PNG or SVG. It’s a static web app — everything runs entirely in your browser, hosted for free on GitHub Pages, with no server, no database, and no account required.

Repositori di GitHub · Halaman web

A single-page, no-backend chart builder for publication-ready figures — paste your data, style it, lay it out, and export print-quality PNG/SVG. 100% client-side, hosted free on GitHub Pages.

HTML5 CSS3 JavaScript D3.js Fabric.js MathJax math.js Papa Parse SheetJS AG Grid Google Fonts Material Symbols Iconify Backend Powered by GitHub Pages License

GitHub stars GitHub last commit GitHub issues Website

🔗 apps: defani.github.io/Ploots-click

Table of Contents

What is this?

Ploots Click is a client-side-only web app: open the page (or visit the GitHub Pages link below) and everything — data parsing, chart rendering, maps, page layout, and export — happens locally in your browser tab (maps fetch their basemap tiles online). Nothing you paste or upload is ever sent to a server, because there is no server. The app is just static HTML, CSS, and JavaScript, deployed straight from this repository via GitHub Pages, which is why it costs nothing to run and needs zero setup.

⬆️ Back to Table of Contents

Desktop app

Ploots Click also runs as a desktop app for Windows, built with Tauri 2 like GeoLibre Desktop. It uses the system’s WebView2, so the installer is small.

Install: download Ploots Click_<version>_x64-setup.exe (or the .msi) from the repository’s Releases page, or from the “ploots-click-windows” artifact of the Desktop app workflow run. The setup installs for the current user only and does not need administrator rights. If WebView2 is missing, the installer gets it.

Build it yourself (Windows):

  1. Install Rust, the Visual Studio Build Tools with the “Desktop development with C++” workload, Python 3, and the Tauri CLI (cargo install tauri-cli --version "^2" --locked, or npm install -g @tauri-apps/cli@^2 with Node.js).

  2. Build the offline copy of the web app into desktop/dist. Downloads are cached in desktop/.cache:

    python desktop/build_dist.py
  3. Build the installers from the desktop folder with cargo tauri build (or tauri build with the npm CLI). They land in desktop/src-tauri/target/release/bundle/nsis/ and …/msi/.

The GitHub workflow .github/workflows/desktop.yml runs the same steps on every push that changes the app. Pushing a desktop-v* tag publishes a release.

⬆️ Back to Table of Contents

Interface

The app opens on a Home screen: make a Chart from tabular data or a Map from spatial data, blank or from a sample.

Home screen with the Chart and Map startsPloots Click editor: chart type gallery on the left, a grouped bar chart on an A4 page, Design panel on the right

Everything is set from one sidebar on the left, so the page keeps the rest of the window. Its rail is grouped by task — Home · Data (charts) or Map (maps) · Canvas, Design, Layers · Chart, Axis, Legend, Style (charts) · Shapes, LaTeX · Export — and each mode only shows the menus it uses. The page canvas has rulers, the mouse wheel zooms, and a dark theme is one click away (moon icon):

The same editor in dark theme

Live app: defani.github.io/Ploots-click

⬆️ Back to Table of Contents

Features

Charts

Every chart type, rendered by the D3 engine from its built-in sample data (click an image to open it full size):


Bar – single

Bar – grouped

Bar – stacked

Lollipop

Dumbbell / slope

Line

Area

Scatter

Bubble

Pie

Donut

Radial rings

Sunburst

Histogram

Box plot

Violin plot

Ridge plot

Heatmap

Waterfall

Funnel

Treemap

Sankey

Scatter matrix

Choropleth map

Bubble map

Choropleth map scoped to Europe, with the map settings panel open in the sidebar
Map settings: base map (world or custom GeoJSON), scope, projection, continuous or classed colour, value range.

Data View

Data View: chart mapping shelves on the left, editable data table on the right

Editor: toolbars, Design panel & layers

Canva-style floating toolbar. Selecting text shows its format bar above the canvas (font, size, colour, bold/italic/underline/strike, case, alignment, lists, super/subscript, line spacing, opacity, effects, position), plus a small action bar next to the object (duplicate, lock, delete, more):

Selected text annotation with the floating text toolbar and the Design panel

Shapes and other objects get the same kind of floating bar (fill, stroke, dash, opacity, position). A Figma-style size badge (W × H) sits under the selection, with dashed distance guides to the page’s left and top edges. The Design panel edits position, alignment to the page, rotation and flips, size (with a proportion lock), opacity, corner radius, fill, stroke and drop shadow:

Highlight rectangle selected, showing the floating object bar and the Design panel

Advanced colour picker with solid or gradient fills (linear/radial, angle, draggable colour stops), HSV area, hue and alpha sliders, Hex/RGB/HSL input, an eyedropper, saved swatches and the colours already used on the page:

Colour picker in gradient mode

Layers lists every object on the page (with thumbnails, type and font details): drag to reorder, rename, hide, lock, and group/ungroup. The chart itself always stays at the back:

Layers panel with two text objects, a rectangle and the chart

Sidebar panels for the axes, style and legend:


Axis

Color & style

Legend

Export

Map workspace (GIS)

Pick Map on the Home screen (or the Map button in the rail) and the page’s chart block becomes a MapLibre GL map frame, driven by its own Map panel. It works like a small QGIS print layout:

Map workspace: ASEAN countries in graduated colors with a legend, scale bar, north arrow, inset map and coordinate grid on an A4 pageCategorized map on Esri World Imagery with the scale bar selected and its properties in the Map panelAttribute table under the map with two features selected, and the map tool bar with the Select tool active

KoboToolbox monitoring

The Kobo button in the rail (map mode) connects to a KoboToolbox server (Global, EU, OCHA or your own) with your API token and lists your forms. Pick a form and open the monitoring dashboard:

Filters for date range and enumerator apply to every tab. Auto refresh (every 1 to 30 minutes) fetches only new submissions and shows a notification with who sent them. Fields for enumerator, respondent, village, area, survey date and location are detected from common names and can be changed. Quality checks flag short interviews, missing GPS and poor GPS accuracy.

Why a proxy is needed. The KoboToolbox API does not allow requests from other websites (CORS), so a browser page cannot read it directly. Run the small proxy in tools/ on your computer; it only forwards read-only /api/v2/ requests to Kobo servers, listens on 127.0.0.1 only, and never stores your token:

python tools/kobo_proxy.py

Add --allow-host kobo.example.org for a self-hosted server. Add --demo to also serve a generated demo form, “Coffee farmer baseline (demo)”: five enumerators near Takengon over the last ten days, with today’s submissions arriving through the day. The demo lets you try the dashboard without an account.

Chat with Claude

The round Claude button opens a chat bubble. It connects Ploots Click to the geolibre-live MCP server (the same server used by the GeoLibre Live MCP Bridge plugin) at ws://127.0.0.1:9878. With that server registered in Claude Desktop or Claude Code:

The server keeps one app connection and the newest one wins, so a GeoLibre window with the bridge plugin and Ploots Click take turns. If another app takes over, the bubble shows it and does not reconnect by itself. Connecting by hand turns on auto-connect for your next visit.

Files (folder browser)

Like the QGIS Browser panel: Files in the left rail connects one or more folders on your computer. They are remembered for the next session; the browser or the desktop app asks again for permission when needed. Browse them as a tree and filter by name, then double-click (or press Enter on) a file to open it:

Working with files:

Selecting a file shows a preview before it is opened: the first rows of a CSV or Excel sheet (with the list of sheets), a thumbnail map of a vector file with its feature count, geometry type and fields, an image thumbnail, or a plugin’s name and description. Expanded folders are remembered.

Files are read from disk when opened; nothing is copied or uploaded. This uses the File System Access API (Chrome, Edge and the desktop app). In other browsers, a folder can be read for the current session only.

When the app opens, an intro says “Welcome to Ploots Click”: personal GIS, data analysis, visualization and field monitoring, a private tool of Defani Arman Alfitriansyah, for personal use only and not for distribution.

Sign-in. The intro also asks for a username and password.

This lock protects the app on a device. It is not encryption: someone with the app’s files and the know-how can get past it. To keep the software itself private, keep the repository private and turn GitHub Pages off.

Plugins

Add features without changing the app, the same way as GeoLibre plugins. Plugins in the left rail installs a plugin from a .zip, a folder or a plugin.json URL (a .zip can also be dropped on the panel). Each installed plugin can be enabled, disabled, reloaded, downloaded as a .zip or removed. Installed plugins are kept in the browser (or the desktop app) and load at startup.

A plugin is a folder with a plugin.json manifest and one ES module that exports activate(app) / deactivate(app). Through app, a plugin can:

Everything a plugin adds is removed when it is disabled. New plugin downloads a working starter to edit. The API is documented in PLUGINS.md, and an example plugin is in plugins/examples/map-coordinates/ (cursor coordinates in decimal degrees, DMS or UTM).

Page layout & annotation

Export

⬆️ Back to Table of Contents

Architecture

Everything below happens in a single browser tab — there’s no backend, no build step, and no network call other than fetching static assets (libraries from a CDN on first use, base maps from this repo).

High-level data flow, from raw input to exported file:

GitHub renders Mermaid with raw HTML/<img> stripped from node labels, so logos can’t sit inside the boxes above — this legend maps each engine to its stage instead:

StageEngine
CSV/TSV parsingPapa Parse
Excel importSheetJS
Chart renderingD3.js
Layout canvas / shapes / textFabric.js
LaTeX formulas on canvasMathJax

Data View: wide ↔ long/tidy and field mapping, the step between raw parsed rows and the chart’s series:

⬆️ Back to Table of Contents

Project structure

.
├── index.html                     # App shell, styling, <script>/<link> tags, splash screen
├── sw.js                          # Service worker (network-first cache, so the app also opens offline)
├── manifest.json                  # Web app manifest (installable PWA)
├── js/
│   ├── lazy-loader.js             # Loads CDN libraries on first use (Fabric, Papa Parse, SheetJS, AG Grid, jsPDF, ...)
│   ├── desktop-shell.js           # Desktop app only: opens web links in the default browser
│   ├── plugins.js                 # Plugin manager: install (.zip / folder / URL), enable, the app API, starter
│   ├── file-browser.js            # Files panel: connected folders, tree, open files by type
│   ├── formats.js                 # Shapefile (+ .prj reprojection), KML / KMZ and GPX readers
│   ├── intro.js                   # Launch intro, sign-in / account setup, About and Account dialogs
│   ├── lock.js                    # Password lock: PBKDF2 hash, attempt delays, Lock button, auto-lock, reset
│   ├── chart-builder/             # Chart settings, data and export, in numbered load-order files
│   │   ├── 01-config.js           #   static config: fonts, canvas templates, hatch/dash/marker defs
│   │   ├── 02-state.js            #   shared state object, chart type list, sample data per chart type
│   │   ├── 03-ui-lists.js         #   populates font/template/unit pickers in the sidebar
│   │   ├── 04-data.js             #   parses pasted/imported data into series, series list UI
│   │   ├── 05-style-helpers.js    #   colour/pattern modes, value formatting, error bars
│   │   ├── 06-canvas-units.js     #   canvas size <-> unit conversion
│   │   ├── 07-render.js           #   legacy render() entry point; js/d3-engine/ wraps it and draws every chart
│   │   ├── 08-helpers-export.js   #   string/colour helpers, multi-format export panel (PNG/JPG/SVG/PDF)
│   │   ├── 09-event-wiring.js     #   wires sidebar controls (style, axes, legend, ranges, export)
│   │   ├── 10-view-switcher-init.js # Layout/Data view switcher, boots the chart on load
│   │   ├── 11-choropleth.js       #   choropleth settings (state defaults + "Peta (Choropleth)" sidebar panel)
│   │   ├── 12-radial-rings.js     #   Radial Rings registration + its SVG renderer
│   │   ├── 13-lollipop.js … 20-dumbbell.js # chart type registration + sample data (lollipop, bubble,
│   │   │                          #   sunburst, ridge plot, sankey, scatter matrix, bubble map, dumbbell)
│   ├── d3-engine/                 # The chart engine (see D3-MIGRATION.md)
│   │   ├── 00-core.js             #   PlootsD3 namespace, renderer registry, rich text, patterns, mount
│   │   ├── 01-frame.js            #   shared cartesian frame: scales, axes, ticks, gridlines, titles, legend
│   │   ├── 02-cartesian.js        #   bar (single/grouped/stacked), line, area, scatter
│   │   ├── 03-stats.js            #   pie, donut, histogram, box, violin, heatmap
│   │   ├── 04-flow.js             #   waterfall, funnel, treemap
│   │   ├── 05-special.js          #   lollipop, dumbbell, bubble, scatter matrix, sankey, ridge plot, radial rings, sunburst
│   │   ├── 06-geo.js              #   choropleth and bubble map (d3-geo, local topojson)
│   │   ├── geo-country-regex.js   #   country name -> ISO-3 matching
│   │   └── 99-integration.js      #   hooks the engine into render(), export and the Format Axis panel
│   ├── layout-editor/             # Fabric.js full-page canvas and editor UI, in numbered files
│   │   ├── 01-canvas-core.js      #   canvas setup, chart-proxy sync, stage resize
│   │   ├── 02-toolbar-text.js     #   main toolbar wiring, "Add text" tool
│   │   ├── 03-shapes.js           #   shape picker and the 30 shape geometries
│   │   ├── 04-images.js           #   "Add image" tool
│   │   ├── 05-object-actions.js   #   lock/unlock, duplicate, delete
│   │   ├── 06-context-menu.js     #   right-click menu
│   │   ├── 07-selection.js        #   selection events, which format bar to show
│   │   ├── 08-format-bars.js      #   format bars (text/shape/image/formula) wired to the active object
│   │   ├── 09-panels-helpers.js   #   colour-swatch helpers, side-panel sync
│   │   ├── 10-export-overlay.js   #   flattens all Fabric objects to a transparent PNG for export
│   │   ├── 11-sidebar-nav.js      #   left sidebar panel switching
│   │   ├── 12-theme-init.js       #   dark/light theme, final boot calls
│   │   ├── 13-axis-title-detach.js #  detach X/Y axis titles into free text
│   │   ├── 14-legend-hover.js     #   drag the chart legend on the canvas
│   │   ├── 15-legend-detach.js    #   detach the legend into a free-floating group
│   │   ├── 16-draw-tool.js        #   Pen tool: vector paths with corner and curve anchors
│   │   ├── 17-textbox-resize.js   #   text boxes resize their width instead of stretching the text
│   │   ├── 18-chart-quickbar.js   #   floating quick controls when the chart is selected
│   │   ├── 19-axis-tick-float.js  #   "Axis Tick Line" block in the Axis tab
│   │   ├── 20-canvas-zoom.js      #   zoom slider, Ctrl +/−/0 and Ctrl+wheel zoom
│   │   ├── 21-layers-panel.js     #   Layers tab (reorder, rename, hide, lock, group)
│   │   ├── 22-axis-format-panel.js #  click an axis to open its Format Axis panel
│   │   ├── 23-canvas-pan-scrollbars.js # themed pan scrollbars
│   │   ├── 24-text-float-bar.js   #   Canva-style floating format bars above the canvas
│   │   ├── 25-design-panel.js     #   Figma-style Design tab (position, size, fill/gradient, stroke, shadow)
│   │   ├── 26-selection-hud.js    #   W × H badge and distance guides for the selection
│   │   ├── 27-object-float-bar.js #   floating bars for shapes, images, formulas, groups
│   │   ├── 28-axis-controls-sync.js # keeps the Axis tab's controls and the Format Axis panel in sync
│   │   └── 29-sidebar-design.js   #   Design and Layers as left-sidebar panels; groups the rail per mode
│   ├── gis/                       # Map workspace (MapLibre GL)
│   │   ├── 00-store.js            #   layers (vector / raster / XYZ), selection, export GeoJSON/CSV
│   │   ├── 01-symbology.js        #   single / categorized / graduated (Jenks, quantile, equal)
│   │   ├── 02-map.js              #   the map frame: basemaps, layers, grid, frame, scale, rotation, tools
│   │   ├── 03-items.js            #   legend, scale bar, north arrow, inset map as page items
│   │   ├── 04-raster.js           #   GeoTIFF reading and rendering (geotiff.js)
│   │   ├── 05-attribute-table.js  #   attribute table dock
│   │   ├── 06-panel.js            #   the Map panel
│   │   ├── 07-home.js             #   Home screen
│   │   ├── 08-catalog.js          #   data catalog: government ArcGIS, GFW, GBIF, iNaturalist
│   │   ├── 09-layer-menu.js       #   layer menu, filter / select by expression, field calculator, properties
│   │   ├── 10-bridge.js           #   Claude bridge (geolibre-live MCP over WebSocket) and chat bubble
│   │   └── 11-kobo.js             #   KoboToolbox connector, monitoring dashboard, route animation, data API
│   ├── data_view.js               # Data View: AG Grid table, wide/long reshape, transpose
│   ├── dv_shelves.js              # Data View chart-mapping shelves (drag fields onto X / Y)
│   ├── data_formulas.js           # Data View spreadsheet formulas (=SUM, =AVERAGE, ...)
│   ├── data_stats.js              # Data View column statistics (plain JS)
│   ├── color_picker.js            # Colour picker: solid/gradient, HSV, eyedropper, swatches
│   ├── palettes.js                # Built-in palette catalog, grid and search
│   ├── canvas_background.js       # Page background colour
│   ├── canvas_ruler.js            # Rulers on the canvas edges + draggable guide lines
│   ├── latex_symbols.js           # LaTeX (MathJax) formulas on canvas + the symbol/unit catalog
│   ├── help_search.js             # Help search: find a menu or setting by name
│   ├── ui_sections.js             # Collapsible sidebar sections
│   └── undo_redo.js               # Global undo/redo history
├── PLUGINS.md                     # How to write a plugin, and the app API
├── plugins/examples/              # Example plugin (map-coordinates)
├── tools/
│   └── kobo_proxy.py              # Local KoboToolbox API proxy (CORS) with an optional demo form
├── desktop/                       # Windows desktop app (Tauri 2)
│   ├── build_dist.py              #   offline copy of the web app into desktop/dist (libraries, fonts, icons local)
│   ├── make_icons.py              #   app icons from the logo
│   └── src-tauri/                 #   Rust shell: window, installers, native Kobo requests (kobo_get)
├── vendor/
│   ├── d3-7.9.0.min.js            # D3.js 7.9.0, bundled locally
│   └── topojson/                  # Natural Earth base maps (*_110m.json) for the map chart types
├── assets/
│   ├── logo_light.png, logo_dark.png # Topbar logo marks
│   ├── palettes.png               # Palette catalog image (used in this README)
│   └── screenshots/               # README screenshots; charts/ holds one image per chart type
├── D3-MIGRATION.md                # How the Plotly -> D3 migration was done, stage by stage
├── BUGFIXES.md                    # Notes on notable bug fixes
├── LICENSE                        # MIT license
├── THIRD-PARTY-NOTICES.md         # Notices for bundled D3.js, country-regex and the topojson base maps
└── README.md

LaTeX & Symbol Catalog

The formula box ($...$) is rendered live via MathJax, so any valid LaTeX math syntax works there, not just what’s listed below. The 104-symbol catalog is a curated, one-click subset for the symbols and units that come up most often in scientific figures — searchable by name or LaTeX code, and insertable directly onto the canvas without typing.

Greek (34)
SymbolNameLaTeX
αalpha\alpha
βbeta\beta
γgamma\gamma
δdelta\delta
εepsilon\epsilon
ζzeta\zeta
ηeta\eta
θtheta\theta
ιiota\iota
κkappa\kappa
λlambda\lambda
μmu\mu
νnu\nu
ξxi\xi
πpi\pi
ρrho\rho
σsigma\sigma
τtau\tau
υupsilon\upsilon
φphi\phi
χchi\chi
ψpsi\psi
ωomega\omega
ΓGamma\Gamma
ΔDelta\Delta
ΘTheta\Theta
ΛLambda\Lambda
ΞXi\Xi
ΠPi\Pi
ΣSigma\Sigma
ΥUpsilon\Upsilon
ΦPhi\Phi
ΨPsi\Psi
ΩOmega\Omega
Operators (26)
SymbolNameLaTeX
±plus-minus\pm
∓minus-plus\mp
×times\times
÷divide\div
·dot product\cdot
√square root\sqrt{}
∑summation\sum_{i=1}^{n}
∏product\prod_{i=1}^{n}
∫integral\int_{}^{}
∮contour integral\oint
∂partial derivative\partial
∇nabla\nabla
∞infinity\infty
≈approximately\approx
≠not equal\neq
≤less or equal\leq
≥greater or equal\geq
≡equivalent\equiv
∝proportional to\propto
∼similar to\sim
≅congruent to\cong
⊥perpendicular\perp
∥parallel\parallel
∠angle\angle
°degree^{\circ}
′prime\prime
Units (21)
SymbolNameLaTeX
m²square metrem^{2}
m⁻²per square metrem^{-2}
km²square kilometrekm^{2}
cm³cubic centimetrecm^{3}
ha⁻¹per hectareha^{-1}
Mg ha⁻¹megagram per hectareMg\,ha^{-1}
g C m⁻²grams carbon per m²g\,C\,m^{-2}
g cm⁻³densityg\,cm^{-3}
kg m⁻³kg per m³kg\,m^{-3}
W·m⁻²·sr⁻¹·µm⁻¹spectral radianceW\,m^{-2}\,sr^{-1}\,\mu m^{-1}
µmmicrometre\mu m
nmnanometrenm
°Cdegrees Celsius^{\circ}C
%percent\%
‰per mille\u2030
R²coefficient of determinationR^{2}
p<.05p-valuep < 0.05
n=sample sizen =
x̄sample mean\bar{x}
σstandard deviation\sigma
×10ⁿscientific notation\times 10^{n}
Arrows (8)
SymbolNameLaTeX
→right arrow\rightarrow
←left arrow\leftarrow
↔left-right arrow\leftrightarrow
⇒implies\Rightarrow
⇔if and only if\Leftrightarrow
↑up arrow\uparrow
↓down arrow\downarrow
↦maps to\mapsto
Sets & Logic (15)
SymbolNameLaTeX
∈element of\in
∉not an element of\notin
⊂subset\subset
⊆subset or equal\subseteq
∪union\cup
∩intersection\cap
∀for all\forall
∃there exists\exists
¬not\neg
∧and\wedge
∨or\vee
∅empty set\emptyset
ℝreal numbers\mathbb{R}
ℕnatural numbers\mathbb{N}
ℤintegers\mathbb{Z}

Quick-insert structure templates (fraction, superscript, subscript, roots, summation/product/integral with bounds, limit, vector, overline, hat, binomial coefficient, 2×2 matrix) splice their LaTeX skeleton in at the cursor with the caret already placed where you’d start typing.

Color Palettes — sources & licensing

106 built-in palettes: the original 49, 50 more (the rest of the ColorBrewer diverging/sequential families, common Matplotlib scientific colormaps, and the Okabe-Ito colorblind-safe set) and 7 extra custom sets. All colors are hard-coded hex arrays baked into palettes.js — no palette library is bundled or loaded at runtime.

All 106 built-in color palettes

Two names from the original 49 were corrected to match their real source values so the catalog doesn’t carry two different names for the same standard scale: “Ocean Blues” → Blues and “Forest Greens” → Greens (both ColorBrewer sequential palettes, recolored to the actual ColorBrewer hex values in the process).

PalettesInspired by / sourceLicense
Matplotlib tab10, tab20, tab20b, tab20cMatplotlib default qualitative color cyclesMatplotlib license (BSD-style, PSF-based)
Viridis, Plasma, Inferno, Magma, CividisMatplotlib’s perceptually-uniform colormaps (Viridis by Stéfan van der Walt & Nathaniel Smith; Cividis by Nuñez, Anderton & Renslow)CC0 / public domain
Coolwarm, TwilightMatplotlib colormaps (Coolwarm: Kenneth Moreland’s diverging scale; Twilight: van der Walt & Smith)Matplotlib license / CC0
Jet, HSV, Rainbow, Cool, Hot, Copper, Bone, Pink, Spring, Summer, Autumn, Winter, Prism, Ocean, Terrain, CMRmap, Gist Rainbow, Gist Earth, Gist Stern, Gist Ncar, Nipy Spectral, Cubehelix, Gnuplot, Wistia, TurboClassic scientific/MATLAB-style colormaps as shipped in Matplotlib (Turbo by Anton Mikhailov / Google AI; Cubehelix by Dave Green; CMRmap by Carey Rappaport)Matplotlib license; Turbo is Apache License 2.0
ColorBrewer Set1–3, Paired, Dark2, Accent, Pastel1–2, Spectral, BrBG, PiYG, PRGn, PuOr, RdBu, RdGy, RdYlBu, RdYlGn, Blues, Greens, Oranges, Purples, Reds, BuGn, BuPu, GnBu, OrRd, PuBu, PuBuGn, PuRd, RdPu, YlGn, YlGnBu, YlOrBr, YlOrRdColorBrewer by Cynthia Brewer (Penn State)Apache License 2.0
Seaborn Deep, Muted, Bright, Pastel, ColorblindSeaborn default qualitative palettesBSD 3-Clause
SolarizedSolarized by Ethan SchoonoverMIT
NordNord by Sven GrebMIT
DraculaDracula ThemeMIT
Material DesignGoogle Material Design color systemCC BY 4.0
Flat UIFlat UI ColorsFree to use
Okabe-ItoOkabe & Ito (2008), “Color Universal Design” colorblind-safe palettePublic domain / free to use
Mangrove (default), Forest Canopy, Ocean Depth, Sunset Clay, Autumn Harvest, Grayscale, Earth Tones, Pastel Rainbow, Neon Bright, Sunset Gradient, Ice Blues, Berry Mix, Copper & Rust, Royal Jewel Tones, Retro 80s, Monochrome Blue, Corporate Navy & Gold, Slate & Steel, Custom Palette 1–7Original combinations created for this project — not derived from an external named scale—

Fonts — sources & licensing

Five typefaces are offered for the title/subtitle, chart body/axes/legend, and the LaTeX/symbol tool. None of the font files themselves are bundled in this repo — they’re referenced by CSS font-family stacks and resolved either from Google Fonts (loaded via CDN <link> in index.html) or from whatever the visitor’s system already has installed, with generic serif/sans-serif fallbacks either way.

FontSourceLicense
PoppinsGoogle Fonts, loaded live from fonts.googleapis.com; designed by Indian Type FoundrySIL Open Font License 1.1
CambriaMicrosoft ClearType Font Collection (system font — ships with Windows/Office; falls back to Georgia)Proprietary (Microsoft) — used via system font stack only, not redistributed
Times New RomanMonotype (system font)Proprietary (Monotype) — used via system font stack only, not redistributed
ArialMonotype (system font)Proprietary (Monotype) — used via system font stack only, not redistributed
Cambria MathMicrosoft (system font — ships with Windows/Office; falls back to STIX Two Math, then Latin Modern Math)Proprietary (Microsoft); fallbacks STIX Two Math (SIL OFL 1.1) and Latin Modern Math (GUST Font License)

Because Cambria, Times New Roman, Arial, and Cambria Math are only ever referenced by name in a CSS font stack — never packaged as font files in this repository — a visitor without them installed silently gets the listed fallback (or their browser/OS default serif or sans-serif) instead.

Icons — sources & licensing

Icons across the topbar, sidebar, and Data View ribbon come from a webfont icon set, Iconify web components, and a few hand-drawn inline SVGs. Nothing here is bundled as a font/icon file in the repo — Material Symbols loads live from Google Fonts, Iconify icons are fetched on demand by the iconify-icon component, and the custom SVGs are written directly in index.html.

Icon setUsed forSourceLicense
Material Symbols (Rounded)The large majority of toolbar, sidebar, and ribbon iconsGoogle Fonts Icons, loaded live via CDN <link>Apache License 2.0
Custom inline SVGChart-type thumbnails, draw-tool shape picker, sidebar nav marks, and export-format icons not covered by Material SymbolsOriginal artwork drawn for this projectProject license (MIT)
Iconify — Material Design Icons (mdi:)Chart-type tiles in the Chart panel (loaded via the iconify-icon web component)Iconify (aggregator — icon-sets.iconify.design)Apache License 2.0 (Material Design Icons); confirm per set before adding others

Page templates

TemplateSizeUnit
A4 Landscape297 × 210mm
A4 Portrait210 × 297mm
Letter Landscape279.4 × 215.9mm
Letter Portrait215.9 × 279.4mm
Legal Landscape355.6 × 215.9mm
Legal Portrait215.9 × 355.6mm
Presentation 16:91920 × 1080px
Presentation 4:31024 × 768px
Instagram Story1080 × 1920px
Social Square1080 × 1080px

Custom width/height is also available in px, mm, or cm, independent of the templates above.

Fill patterns, dash styles & data-point markers

8 fill/hatch patterns (drawn as SVG patterns by the D3 engine — used whenever a series’ style includes patterns): solid, / diagonal, \ diagonal, x cross, - horizontal lines, | vertical lines, + cross, . dots.

6 line dash styles: solid, dot, dash, longdash, dashdot, longdashdot.

21 data-point marker shapes for line, area, and scatter charts (drives both the plotted marker and its legend icon): Circle, Square, Diamond, Triangle up, Triangle down, Pentagon, Hexagon, Star, Star diamond, Star triangle, Hexagram, Plus (+), X, Hash (#), Asterisk (*), Arrow, Y, Hourglass, Bowtie, Diamond tall, Diamond wide.

Layout shape library

Beyond text boxes, the Layout canvas’s Shapes panel offers 30 drawable shapes across four groups, each editable from its floating bar and the Design panel (fill or gradient, stroke, corner radius, shadow):

Export details

Value label formatting

OptionExample (1234.5)
Auto1234.5 (rounded to 2 decimals, trailing zeros trimmed)
Integer1235
1 decimal1234.5
2 decimals1234.50
Thousands separator1,235
Percent1234.5%
CurrencyRp 1,235 (Indonesian Rupiah formatting, locale id-ID)

Error bars

Applied to every visible series on bar, line, area, and scatter charts (not available on pie/donut/heatmap/box/violin/waterfall/funnel/treemap). Two modes:

Cap width and line thickness are independently adjustable, and the error bar color can either stay black (default, matching print conventions) or follow each series’ own color.

Keyboard shortcuts

ShortcutAction
Ctrl+Z / Ctrl+Y (or Ctrl+Shift+Z)Undo / redo
Ctrl + / Ctrl − / Ctrl 0Zoom in / zoom out / zoom to 100%
Mouse wheelZoom around the pointer (Shift: pan sideways, Alt: pan up/down)
Ctrl+B / Ctrl+I / Ctrl+UBold / italic / underline (text selected)
Delete or BackspaceRemove the selected layout object
Ctrl+C (Data View)Copy the selected cells
Enter / double-click (Pen tool)Finish the path; Backspace removes the last point, Esc leaves the tool
Double-click the mapMove the map content (Pan / Select / Identify); Esc or Done to leave
Shift + click (map Select tool)Add to or remove from the selection

Duplicate, lock, arrange and delete are also on the floating object bar and the right-click menu.

Libraries & versions

LibraryVersionLoaded from
D3.jsbundled (v7.9.0, ISC)local file (vendor/d3-7.9.0.min.js), not CDN
Fabric.js5.3.0cdnjs
MathJax3.2.2 (es5/tex-svg.js)cdnjs
math.js12.4.3cdnjs — expression evaluation in Data View formulas
Papa Parse5.4.1cdnjs
SheetJS (xlsx)0.18.5cdnjs — Excel .xlsx/.xls import
AG Grid Community35.3.0cdnjs
marked16.3.0cdnjs — renders this README as HTML on the splash screen
jsPDF2.5.1cdnjs — PDF export
svg2pdf.js2.2.3jsDelivr — vector charts in PDF export
iconify-icon2.1.0code.iconify.design — chart-type icons
MapLibre GL JS5.9.0cdnjs — the map workspace (loaded when a map is opened)
geotiff.js2.1.3jsDelivr — GeoTIFF raster layers (loaded on first raster)

⬆️ Back to Table of Contents

Known limitations

Click to expand — 7 known limitations

⬆️ Back to Table of Contents

Built with

This project only exists because of the following open-source libraries and free services — a genuine thank-you to everyone who builds and maintains them:

⬆️ Back to Table of Contents

License

Released under the MIT License. Bundled third-party code (vendor/d3-7.9.0.min.js, ISC) keeps its own notice — see THIRD-PARTY-NOTICES.md.

⬆️ Back to Table of Contents

Purpose & Acknowledgements

This project was not built to compete with established data visualization software or commercial charting tools. Rather, its core purpose is simply to utilize available open-source technologies to make the process of creating publication-ready plots as easy, accessible, and lightweight as possible. It is especially dedicated to students and researchers who might not have coding experience or the budget to access premium software, with the hope that the features provided here can assist in their research and academic work.

Ploots Click draws heavy inspiration from the many incredible charting tools, design systems, and data communities out there. A massive thank you to all the creators of the underlying engines and open-source libraries that power this tool. A special thanks to GitHub for providing GitHub Pages, which makes hosting this static web app for free possible.

I am always open to feedback and suggestions. Ultimately, I am just a student utilizing a little bit of knowledge with the help of official documentation and AI tools like Claude, ChatGPT (for brainstorming), and Gemini to help bring this idea to life. To every developer, library maintainer, and supporter—thank you. This tool is built on the shoulders of your hard work.

⬆️ Back to Table of Contents

Feedback & Contributions

Since I am always open to feedback and suggestions, if you find a bug, have a feature request, or just want to share how you use Ploots Click in your research, please feel free to open an Issue in this repository.

You don’t need to be a programmer to contribute—bug reports, design ideas, and usability feedback are incredibly valuable!

⬆️ Back to Table of Contents

Author

Built by Defani Arman Alfitriansyah.