{"id":93,"date":"2026-05-29T16:23:16","date_gmt":"2026-05-29T16:23:16","guid":{"rendered":"https:\/\/geo.edesma.org\/blog\/?p=93"},"modified":"2026-06-02T01:34:41","modified_gmt":"2026-06-02T01:34:41","slug":"qgis-layer-viewer-2","status":"publish","type":"post","link":"https:\/\/geo.edesma.org\/blog\/?p=93&lang=en","title":{"rendered":"QGIS Layer Viewer"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">QGIS Layer Viewer is a lightweight, serverless web map viewer that reads QGIS Layer Definition files (.qlr) and GeoJSON data directly in the browser, rendering them on an <span data-wp-title=\"OpenLayers\" data-wp-lang=\"en\" data-wikipedia-preview=\"\" class=\"wmf-wp-with-preview\">OpenLayers<\/span> map with styling that closely matches the original QGIS project \u2014 including categorized and graduated symbology, dash patterns, glow effects, SVG markers, labels, and map tips.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">No backend, no server-side processing, no upload to any cloud service. Files are read locally or fetched from a URL. Everything runs in the browser. Deploy by copying two files to any static web server.<\/p>\n\n\n\n<!--more Continue reading-->\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Who is it for?<\/strong> GIS professionals who work in QGIS and need to share styled maps on the web without rebuilding symbology from scratch.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>What problem does it solve?<\/strong> The gap between a styled QGIS layer and a publishable web map. Export the .qlr, pair it with a GeoJSON, drop both into the viewer \u2014 done.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>What is it not?<\/strong> A full GIS editor. It does not support raster layers or WMS. It is a read-only preview and sharing tool.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can access the live application <a href=\"https:\/\/geo.edesma.org\/qgisviewer\/index.html\" target=\"_blank\" rel=\"noreferrer noopener\">here<\/a>. You can also install the application on your own server by downloading the HTML and JavaScript files at this <a href=\"https:\/\/geo.edesma.org\/blog\/wp-admin\/post.php?post=164\" target=\"_blank\" rel=\"noreferrer noopener\">link<\/a>, where you will also find sample data to practice with.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">UI Explained<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n<div class=\"wp-block-image wp-custom-css-f44c26ef\">\n<figure class=\"aligncenter size-full is-resized has-custom-css\"><img loading=\"lazy\" decoding=\"async\" width=\"849\" height=\"528\" src=\"https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/QGISLayerViewer_1-1.png\" alt=\"\" class=\"wp-image-100\" style=\"width:500px\" srcset=\"https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/QGISLayerViewer_1-1.png 849w, https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/QGISLayerViewer_1-1-300x187.png 300w, https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/QGISLayerViewer_1-1-768x478.png 768w\" sizes=\"auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px\" \/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\"><br>A resizable panel on the left contains all controls. The panel is resizable by dragging its right border (220\u2013520px). The map fills the remaining viewport.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Drag and Drop Interface<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Drag and drop files means letting users add layer files from their operating system (e.g., Windows Explorer, macOS Finder) directly into the application. The controls are located at the top of the left panel.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"289\" height=\"222\" src=\"https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/Drag-Drop.png\" alt=\"\" class=\"wp-image-23\"\/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">There are three (3) options to add layers.<\/p>\n\n\n\n<ul class=\"wp-block-list lista-indentada has-custom-css wp-custom-css-9ff9fb88\">\n<li>GeoJSON plus a <strong>QGIS Layer Definition File<\/strong> (QLR)<\/li>\n\n\n\n<li class=\"has-custom-css wp-custom-css-ff57d872\">A QLR file that internally references a data source<\/li>\n\n\n\n<li>A QGIS Layer Viewer export file in <strong>.qview<\/strong> format.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Any number of layers can be loaded in sequence.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">GeoJSON plus QLR<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">GeoJSON + QLR is the default option.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">GeoJSON is a geospatial data interchange format based on JavaScript Object Notation (JSON). It defines several types of JSON objects and the manner in which they are combined to represent data about geographic features, their properties, and their spatial extents.<br><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Although the Internet Engineering Task Force (IETF) published RFC 7946 in 2016 establishing a strict rule \u2014 intended to simplify interoperability across the web \u2014 that GeoJSON must use WGS 84 longitude\u2013latitude coordinates, the reality is that modern GIS software is more flexible. Tools like QGIS allow users to export GeoJSON in any coordinate reference system.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>GeoJSON does not support styles of any kind<\/strong>. The format contains only geometry and attributes. Styling \u2014 colors, line widths, fill patterns, labels, symbols \u2014 must always be handled externally by the software that renders the data. In QGIS Layer Viewer, the style is provided by accompanying the GeoJSON with a QGIS Layer Definition File, or QLR file.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A <code>.qlr<\/code> file in QGIS is a <strong>QGIS Layer Definition File<\/strong>. It stores the symbology (colors, line styles, etc.), labels (text formatting, placement, rendering settings \u2014 transparency, blending modes, etc.) and <strong>other layer properties<\/strong>, but <strong>not the actual data itself<\/strong>. The QLR file only references the data source. The section <a href=\"#symbology\" data-type=\"internal\" data-id=\"#symbology\">Symbology parsed from the QLR<\/a> below has a brief description of how QGIS Layer Viewer handles the imported symbology.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Drop a <code>.geojson<\/code> and its matching <code>.qlr<\/code> in any order and the app matches them by filename stem. Either file can come first; a pending indicator shows which file is waiting for its partner, with a cancel (X) button. The full filename is shown in a tooltip when truncated. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"370\" height=\"265\" src=\"https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/Waiting-for-file.png\" alt=\"\" class=\"wp-image-31\" srcset=\"https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/Waiting-for-file.png 370w, https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/Waiting-for-file-300x215.png 300w\" sizes=\"auto, (max-width: 370px) 85vw, 370px\" \/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\">Drop both files simultaneously and the pairing logic resolves them instantly.<br><\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full is-resized\"><img loading=\"lazy\" decoding=\"async\" width=\"345\" height=\"309\" src=\"https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/Drag-Drop-Files-1.png\" alt=\"\" class=\"wp-image-30\" style=\"aspect-ratio:1.1165278706461614;width:373px;height:auto\" srcset=\"https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/Drag-Drop-Files-1.png 345w, https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/Drag-Drop-Files-1-300x269.png 300w\" sizes=\"auto, (max-width: 345px) 85vw, 345px\" \/><\/figure>\n<\/div>\n\n\n<h3 class=\"wp-block-heading\">QLR with Data Source URL<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">When the QLR file references the URL of the data source, the <strong>QLR + web URL<\/strong> option allows dropping only the .QLR file. The viewer reads and fetches the GeoJSON automatically. Supports ArcGIS FeatureServer with OID-keyset pagination and SQL filter rewriting.<\/p>\n\n\n\n<ul class=\"wp-block-list lista-indentada has-custom-css wp-custom-css-aeb7d6de\">\n<li>ArcGIS FeatureServer with OID-keyset pagination and SQL filter rewriting.<\/li>\n\n\n\n<li>A URL of a GeoJSON file on a remote server, loaded into QGIS using the Data Source Manager.<\/li>\n<\/ul>\n\n\n\n<h5 class=\"wp-block-heading\">Import file format <strong>.qview<\/strong><\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">A <code>.qview<\/code> file is a self-contained portable map created by QGIS Layer Viewer. It bundles everything needed to reproduce a map session into a single JSON file \u2014 the raw QLR styling, the complete feature data, and all user-edited settings \u2014 so the recipient can open it by dropping it into any instance of the viewer with no additional files, no GIS software, and no internet connection required. Read about <a href=\"#ExportQview\">exporting a .qview file below<\/a>.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><br><strong>Layer control<\/strong><\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Below the drag and drop section is the layer control, the central place to manage all layers in the project \u2014 controlling their <strong>visibility<\/strong>, <strong>order<\/strong>, <strong>grouping<\/strong>, and <strong>styling<\/strong>.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"396\" height=\"361\" src=\"https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/layer-control.png\" alt=\"\" class=\"wp-image-41\" srcset=\"https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/layer-control.png 396w, https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/layer-control-300x273.png 300w\" sizes=\"auto, (max-width: 396px) 85vw, 396px\" \/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Each layer is displayed with a color-coded border according to its geometry type \u2014 cyan for points, green for lines, orange for polygons \u2014 and offers individual controls: a visibility toggle, a remove button with confirmation, and an expandable row with more detailed settings.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"790\" height=\"262\" src=\"https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/layers-buttons.png\" alt=\"\" class=\"wp-image-53\" srcset=\"https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/layers-buttons.png 790w, https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/layers-buttons-300x99.png 300w, https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/layers-buttons-768x255.png 768w\" sizes=\"auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<ul class=\"wp-block-list lista-indentada has-custom-css wp-custom-css-208dc452\">\n<li>A Table icon opens the attribute table viewer for that layer.<\/li>\n\n\n\n<li>Pencil icon (\u270f) opens the Edit Layer modal.<\/li>\n\n\n\n<li>The Visibility toggle (eye icon) per layer; turns red when hidden.<\/li>\n\n\n\n<li>Remove layer with confirmation dialog.<\/li>\n\n\n\n<li>Expandable row: opacity slider (live), Labels toggle, Map tips toggle, and description text.<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">Expanding a layer reveals the opacity slider (with real-time effect), the labels toggle, the map tips toggle, and, when available, the layer&#8217;s description text taken directly from the <code>.qlr<\/code> file.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">There is no limit to the number of layers that can be loaded. The viewer automatically stacks them in a logical order: polygons at the bottom, lines in the middle, and points on top. This order can be changed at any time by dragging layers within the side panel, and the map updates immediately. Each time a new layer is added, the map automatically adjusts the view to show the full extent of all loaded layers.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Labels<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Labels are read from the <code>&lt;labeling type=\"simple\"&gt;<\/code> block in the <code>.qlr<\/code> file. They must be configured and enabled in QGIS before exporting. The viewer supports font family, weight, color, size (with unit conversion), and text buffer (halo).<\/p>\n\n\n\n<!-- QGIS Layer Viewer \u2014 Labeling Support block -->\n\n<style>\n.qlv-label {\n    font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n    background: #ffffff;\n    border: 1px solid #e5e7eb;\n    border-radius: 12px;\n    padding: 20px 24px;\n    max-width: 620px;\n    box-sizing: border-box;\n}\n.qlv-label-header {\n    display: flex;\n    align-items: center;\n    gap: 10px;\n    margin-bottom: 12px;\n}\n.qlv-label-badge {\n    background: #f3f4f6;\n    border: 1px solid #e5e7eb;\n    border-radius: 8px;\n    padding: 5px 10px;\n    font-family: \"Courier New\", Courier, monospace;\n    font-size: 13px;\n    color: #111827;\n    font-weight: 600;\n}\n.qlv-label-title {\n    font-size: 15px;\n    font-weight: 600;\n    color: #111827;\n    margin: 0;\n}\n.qlv-label-intro {\n    font-size: 13px;\n    color: #6b7280;\n    line-height: 1.7;\n    margin: 0 0 16px;\n}\n.qlv-label-intro code {\n    font-family: \"Courier New\", Courier, monospace;\n    font-size: 12px;\n    background: #f3f4f6;\n    padding: 1px 5px;\n    border-radius: 3px;\n    color: #374151;\n}\n.qlv-section-label {\n    font-size: 11px;\n    font-weight: 600;\n    text-transform: uppercase;\n    letter-spacing: .07em;\n    color: #9ca3af;\n    margin: 0 0 10px;\n}\n.qlv-divider {\n    border: none;\n    border-top: 1px solid #e5e7eb;\n    margin: 16px 0;\n}\n.qlv-props-2col {\n    display: grid;\n    grid-template-columns: 1fr 1fr;\n    gap: 8px;\n    margin-bottom: 0;\n}\n@media (max-width: 420px) {\n    .qlv-props-2col { grid-template-columns: 1fr; }\n}\n.qlv-label-prop {\n    background: #f9fafb;\n    border: 1px solid #e5e7eb;\n    border-radius: 8px;\n    padding: 10px 12px;\n}\n.qlv-label-prop-name {\n    font-family: \"Courier New\", Courier, monospace;\n    font-size: 11px;\n    color: #2563eb;\n    font-weight: 600;\n    margin: 0 0 3px;\n}\n.qlv-label-prop-desc {\n    font-size: 12px;\n    color: #6b7280;\n    line-height: 1.5;\n    margin: 0;\n}\n.qlv-placement-row {\n    display: grid;\n    grid-template-columns: repeat(3, 1fr);\n    gap: 8px;\n}\n@media (max-width: 480px) {\n    .qlv-placement-row { grid-template-columns: 1fr; }\n}\n.qlv-placement-tile {\n    background: #f9fafb;\n    border: 1px solid #e5e7eb;\n    border-radius: 8px;\n    padding: 10px 12px;\n    text-align: center;\n}\n.qlv-placement-geom {\n    font-size: 12px;\n    font-weight: 600;\n    color: #111827;\n    margin: 0 0 4px;\n}\n.qlv-placement-mode {\n    font-family: \"Courier New\", Courier, monospace;\n    font-size: 11px;\n    color: #2563eb;\n    display: block;\n    margin-bottom: 4px;\n}\n.qlv-placement-note {\n    font-size: 11px;\n    color: #9ca3af;\n    margin: 0;\n    line-height: 1.4;\n}\n.qlv-unit-grid {\n    display: grid;\n    grid-template-columns: 1fr 1fr 1fr;\n    gap: 0;\n    border: 1px solid #e5e7eb;\n    border-radius: 8px;\n    overflow: hidden;\n}\n.qlv-unit-header {\n    background: #f3f4f6;\n    font-size: 11px;\n    font-weight: 600;\n    text-transform: uppercase;\n    letter-spacing: .06em;\n    color: #6b7280;\n    padding: 7px 10px;\n    border-bottom: 1px solid #e5e7eb;\n}\n.qlv-unit-cell {\n    font-size: 12px;\n    color: #374151;\n    padding: 7px 10px;\n    border-bottom: 1px solid #f3f4f6;\n    line-height: 1.4;\n}\n.qlv-unit-cell:last-child,\n.qlv-unit-header:last-child {\n    border-right: none;\n}\n.qlv-unit-cell code {\n    font-family: \"Courier New\", Courier, monospace;\n    font-size: 11px;\n    color: #2563eb;\n}\n.qlv-unit-warn {\n    background: #fffbeb;\n    color: #92400e;\n    font-size: 11px;\n}\n.qlv-unit-row-divider {\n    grid-column: 1 \/ -1;\n    border: none;\n    border-top: 1px solid #e5e7eb;\n    margin: 0;\n    height: 0;\n}\n<\/style>\n\n<div class=\"qlv-label\">\n\n    <div class=\"qlv-label-header\">\n        <span class=\"qlv-label-badge\">.qlr<\/span>\n        <p class=\"qlv-label-title\">Labeling support<\/p>\n    <\/div>\n\n    <p class=\"qlv-section-label\">Properties parsed from the QLR<\/p>\n    <div class=\"qlv-props-2col\">\n\n        <div class=\"qlv-label-prop\">\n            <p class=\"qlv-label-prop-name\">&lt;text-style&gt; fieldName<\/p>\n            <p class=\"qlv-label-prop-desc\">Feature attribute used as the label text.<\/p>\n        <\/div>\n\n        <div class=\"qlv-label-prop\">\n            <p class=\"qlv-label-prop-name\">&lt;text-style&gt; fontSize + fontSizeUnit<\/p>\n            <p class=\"qlv-label-prop-desc\">Font size with unit \u2014 converted to CSS pixels at load time.<\/p>\n        <\/div>\n\n        <div class=\"qlv-label-prop\">\n            <p class=\"qlv-label-prop-name\">&lt;text-style&gt; fontFamily, fontBold, fontItalic<\/p>\n            <p class=\"qlv-label-prop-desc\">Font family, weight, and style.<\/p>\n        <\/div>\n\n        <div class=\"qlv-label-prop\">\n            <p class=\"qlv-label-prop-name\">&lt;text-style&gt; textColor<\/p>\n            <p class=\"qlv-label-prop-desc\">Label fill color in QGIS RGBA format.<\/p>\n        <\/div>\n\n        <div class=\"qlv-label-prop\">\n            <p class=\"qlv-label-prop-name\">&lt;text-buffer&gt; bufferDraw<\/p>\n            <p class=\"qlv-label-prop-desc\">Whether to draw a halo around the label text.<\/p>\n        <\/div>\n\n        <div class=\"qlv-label-prop\">\n            <p class=\"qlv-label-prop-name\">&lt;text-buffer&gt; bufferSize + bufferColor<\/p>\n            <p class=\"qlv-label-prop-desc\">Halo width in MM and halo color.<\/p>\n        <\/div>\n\n    <\/div>\n\n    <hr class=\"qlv-divider\">\n\n    <p class=\"qlv-section-label\">Label placement by geometry<\/p>\n    <div class=\"qlv-placement-row\">\n\n        <div class=\"qlv-placement-tile\">\n            <p class=\"qlv-placement-geom\">Points<\/p>\n            <span class=\"qlv-placement-mode\">placement: point<\/span>\n            <p class=\"qlv-placement-note\">Label centered on the feature coordinate.<\/p>\n        <\/div>\n\n        <div class=\"qlv-placement-tile\">\n            <p class=\"qlv-placement-geom\">Lines<\/p>\n            <span class=\"qlv-placement-mode\">placement: line<\/span>\n            <p class=\"qlv-placement-note\">Label follows the line orientation automatically.<\/p>\n        <\/div>\n\n        <div class=\"qlv-placement-tile\">\n            <p class=\"qlv-placement-geom\">Polygons<\/p>\n            <span class=\"qlv-placement-mode\">placement: point<\/span>\n            <p class=\"qlv-placement-note\">Label placed at the visual centroid.<\/p>\n        <\/div>\n\n    <\/div>\n\n    <hr class=\"qlv-divider\">\n\n    <p class=\"qlv-section-label\">Font size unit conversion<\/p>\n    <div class=\"qlv-unit-grid\">\n\n        <div class=\"qlv-unit-header\">Unit<\/div>\n        <div class=\"qlv-unit-header\">Conversion<\/div>\n        <div class=\"qlv-unit-header\">Edit modal shows<\/div>\n\n        <div class=\"qlv-unit-cell\"><code>Point<\/code><\/div>\n        <div class=\"qlv-unit-cell\">\u00d7 1.333 px<\/div>\n        <div class=\"qlv-unit-cell\">Label font size (Point)<\/div>\n\n        <div class=\"qlv-unit-cell\"><code>Pixel<\/code><\/div>\n        <div class=\"qlv-unit-cell\">\u00d7 1 px<\/div>\n        <div class=\"qlv-unit-cell\">Label font size (Pixel)<\/div>\n\n        <div class=\"qlv-unit-cell\"><code>MM<\/code><\/div>\n        <div class=\"qlv-unit-cell\">\u00d7 3.78 px<\/div>\n        <div class=\"qlv-unit-cell\">Label font size (MM)<\/div>\n\n        <div class=\"qlv-unit-cell\"><code>Inch<\/code><\/div>\n        <div class=\"qlv-unit-cell\">\u00d7 96 px<\/div>\n        <div class=\"qlv-unit-cell\">Label font size (Inch)<\/div>\n\n        <div class=\"qlv-unit-cell qlv-unit-warn\"><code>MetersAtScale<\/code> \/ <code>MapUnit<\/code><\/div>\n        <div class=\"qlv-unit-cell qlv-unit-warn\">Default 10 px<\/div>\n        <div class=\"qlv-unit-cell qlv-unit-warn\">\u26a0 warning shown in edit modal<\/div>\n\n    <\/div>\n\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Attribute table<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Clicking the table icon on any layer opens a bottom drawer that occupies roughly one third of the screen, keeping the map visible above.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"630\" src=\"https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/table-1024x630.png\" alt=\"\" class=\"wp-image-42\" srcset=\"https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/table-1024x630.png 1024w, https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/table-300x185.png 300w, https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/table-768x472.png 768w, https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/table-1200x738.png 1200w, https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/table.png 1325w\" sizes=\"auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 1362px) 62vw, 840px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Columns can be sorted ascending or descending by clicking their header, and the search box filters all columns simultaneously, showing in real time how many records match. Clicking any row centers the map on that feature and briefly highlights it with a double cyan stroke. The current view \u2014 with any active filters and sort order applied \u2014 can be exported directly as a CSV file.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Map tips<\/strong><\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Hovering over a map feature can display a popup configured directly from the .qlr file. It corresponds to the value or expression set in the Display Name setting in QGIS (Layer Properties &gt; Display) when exporting the <code>.qlr<\/code> file.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"825\" height=\"218\" src=\"https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/QGIS-Display-Name.png\" alt=\"\" class=\"wp-image-44\" srcset=\"https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/QGIS-Display-Name.png 825w, https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/QGIS-Display-Name-300x79.png 300w, https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/QGIS-Display-Name-768x203.png 768w\" sizes=\"auto, (max-width: 709px) 85vw, (max-width: 909px) 67vw, (max-width: 984px) 61vw, (max-width: 1362px) 45vw, 600px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The viewer supports both simple attribute field references via QGIS&#8217;s preview expression, and full HTML templates with field value substitution. The tooltip automatically repositions itself to stay within the screen boundaries. This feature is toggled individually per layer from the side panel and is off by default.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Basemap Switcher<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">A Floating layers-stack button (top-right of map) allows to select among six (6) background maps. It opens a 3\u00d72 grid of live tile previews.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"313\" height=\"288\" src=\"https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/Basemap-Switch.png\" alt=\"\" class=\"wp-image-148\" srcset=\"https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/Basemap-Switch.png 313w, https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/Basemap-Switch-300x276.png 300w\" sizes=\"auto, (max-width: 313px) 85vw, 313px\" \/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\"><br>Six basemaps are availables: OSM, Esri Topo, Esri Streets, Esri Imagery + reference labels overlay, NatGeo, Carto Voyager. The Active basemap is highlighted with purple border. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Closes on outside click.<\/p>\n\n\n\n<h2 id=\"ExportQview\" class=\"wp-block-heading\">Export QGIS Layer Viewer map bundle<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The <strong>\u2193 Export .qview<\/strong> button bundles all layers (QLR + GeoJSON + edited state) into a single portable JSON file with extension <code>.qview<\/code>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">A <code>.qview<\/code> file is a self-contained portable map created by QGIS Layer Viewer. It bundles everything needed to reproduce a map session into a single JSON file \u2014 the raw QLR styling, the complete feature data, and all user-edited settings \u2014 so the recipient can open it by dropping it into any instance of the viewer with no additional files, no GIS software, and no internet connection required.<\/p>\n\n\n\n<ul class=\"wp-block-list lista-indentada has-custom-css wp-custom-css-a3b28b1e\">\n<li>What each layer entry contains<\/li>\n\n\n\n<li>Raw QLR XML \u2014 full QGIS symbology<\/li>\n\n\n\n<li>Complete GeoJSON feature snapshot<\/li>\n\n\n\n<li>Edited layer name and font size<\/li>\n\n\n\n<li>Stack order, opacity, visibility<\/li>\n\n\n\n<li>Key advantage \u2014 ArcGIS live service snapshot<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">When a layer is loaded from an ArcGIS FeatureServer \u2014 even one that required paginating thousands of records \u2014 the complete merged dataset is embedded in the <code>.qview<\/code> at export time. The recipient gets a point-in-time snapshot of the live service with no ArcGIS account or network access needed.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Legend<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The Legend is displayed in a collapsible section at the bottom of the sidebar (collapsed by default). Only layers that are visible are shown.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"424\" height=\"326\" src=\"https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/legend.png\" alt=\"\" class=\"wp-image-46\" srcset=\"https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/legend.png 424w, https:\/\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/legend-300x231.png 300w\" sizes=\"auto, (max-width: 424px) 85vw, 424px\" \/><\/figure>\n<\/div>\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It updates automatically when layers are added, removed, or toggled. SVG swatches are generated inline from parsed symbol properties \u2014 no image hosting required.<\/p>\n\n\n\n<h2 id=\"symbology\" class=\"wp-block-heading symbology\">Symbology parsed from the QLR<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">When a <code>.qlr<\/code> file is dropped into the viewer, its XML is parsed and the symbology is translated into native OpenLayers styles \u2014 no manual reconfiguration needed. The viewer reads three renderer types (<code>singleSymbol<\/code>, <code>categorizedSymbol<\/code>, <code>graduatedSymbol<\/code>) and handles multi-layer symbols, where several sub-layers are stacked inside a single QGIS symbol to produce effects like cased roads or outlined fills.<\/p>\n\n\n\n<!-- QGIS Layer Viewer \u2014 By Geometry Type block -->\n\n<style>\n.qlv-block {\n    font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n    background: #ffffff;\n    border: 1px solid #e5e7eb;\n    border-radius: 12px;\n    padding: 20px 24px;\n    max-width: 620px;\n    box-sizing: border-box;\n}\n.qlv-block-header {\n    display: flex;\n    align-items: center;\n    gap: 10px;\n    margin-bottom: 16px;\n}\n.qlv-badge {\n    background: #f3f4f6;\n    border: 1px solid #e5e7eb;\n    border-radius: 8px;\n    padding: 5px 10px;\n    font-family: \"Courier New\", Courier, monospace;\n    font-size: 13px;\n    color: #111827;\n    font-weight: 600;\n}\n.qlv-block-title {\n    font-size: 15px;\n    font-weight: 600;\n    color: #111827;\n    margin: 0;\n}\n.qlv-section-label {\n    font-size: 11px;\n    font-weight: 600;\n    text-transform: uppercase;\n    letter-spacing: .07em;\n    color: #9ca3af;\n    margin: 0 0 12px;\n}\n.qlv-grid {\n    display: grid;\n    grid-template-columns: repeat(3, 1fr);\n    gap: 10px;\n    margin-bottom: 0;\n}\n@media (max-width: 540px) {\n    .qlv-grid { grid-template-columns: 1fr; }\n}\n.qlv-tile {\n    background: #f9fafb;\n    border: 1px solid #e5e7eb;\n    border-radius: 8px;\n    padding: 12px 14px;\n}\n.qlv-tile-header {\n    display: flex;\n    align-items: center;\n    gap: 7px;\n    font-size: 12px;\n    font-weight: 600;\n    color: #111827;\n    margin-bottom: 8px;\n}\n.qlv-dot-point {\n    display: inline-block;\n    width: 10px; height: 10px;\n    border-radius: 50%;\n    background: #378ADD;\n    flex-shrink: 0;\n}\n.qlv-dot-line {\n    display: inline-block;\n    width: 16px; height: 3px;\n    background: #1D9E75;\n    border-radius: 2px;\n    flex-shrink: 0;\n}\n.qlv-dot-polygon {\n    display: inline-block;\n    width: 12px; height: 10px;\n    background: #EF9F27;\n    border-radius: 2px;\n    flex-shrink: 0;\n}\n.qlv-tile-body {\n    font-size: 12px;\n    color: #6b7280;\n    line-height: 1.65;\n    margin: 0;\n}\n.qlv-tile-body code {\n    font-family: \"Courier New\", Courier, monospace;\n    font-size: 11px;\n    background: #efefef;\n    padding: 1px 4px;\n    border-radius: 3px;\n    color: #374151;\n}\n<\/style>\n\n<div class=\"qlv-block\">\n\n    <div class=\"qlv-block-header\">\n        <span class=\"qlv-badge\">.qlr<\/span>\n        <p class=\"qlv-block-title\">Symbology by geometry type<\/p>\n    <\/div>\n\n    <p class=\"qlv-section-label\">Supported symbol classes<\/p>\n\n    <div class=\"qlv-grid\">\n\n        <div class=\"qlv-tile\">\n            <div class=\"qlv-tile-header\">\n                <span class=\"qlv-dot-point\"><\/span> Points\n            <\/div>\n            <p class=\"qlv-tile-body\">\n                SimpleMarker \u2014 11 shapes including circle, square, star, cross, diamond<br><br>\n                SvgMarker \u2014 base64-embedded or server-hosted, with <code>param()<\/code> color substitution\n            <\/p>\n        <\/div>\n\n        <div class=\"qlv-tile\">\n            <div class=\"qlv-tile-header\">\n                <span class=\"qlv-dot-line\"><\/span> Lines\n            <\/div>\n            <p class=\"qlv-tile-body\">\n                SimpleLine \u2014 solid, dot, dash, dash dot, dash dot dot<br><br>\n                Custom dash patterns<br><br>\n                Outer glow (symbol-layer effectStack)\n            <\/p>\n        <\/div>\n\n        <div class=\"qlv-tile\">\n            <div class=\"qlv-tile-header\">\n                <span class=\"qlv-dot-polygon\"><\/span> Polygons\n            <\/div>\n            <p class=\"qlv-tile-body\">\n                SimpleFill \u2014 fill + outline<br><br>\n                SimpleLine \u2014 outline-only mode<br><br>\n                Outer glow (renderer-level effectStack)\n            <\/p>\n        <\/div>\n\n    <\/div>\n\n<\/div>\n\n\n\n<!-- QGIS Layer Viewer \u2014 Layer-level properties block -->\n\n<style>\n.qlv-props {\n    font-family: -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, sans-serif;\n    background: #ffffff;\n    border: 1px solid #e5e7eb;\n    border-radius: 12px;\n    padding: 20px 24px;\n    max-width: 620px;\n    box-sizing: border-box;\n}\n.qlv-props-header {\n    display: flex;\n    align-items: center;\n    gap: 10px;\n    margin-bottom: 16px;\n}\n.qlv-props-badge {\n    background: #f3f4f6;\n    border: 1px solid #e5e7eb;\n    border-radius: 8px;\n    padding: 5px 10px;\n    font-family: \"Courier New\", Courier, monospace;\n    font-size: 13px;\n    color: #111827;\n    font-weight: 600;\n}\n.qlv-props-title {\n    font-size: 15px;\n    font-weight: 600;\n    color: #111827;\n    margin: 0;\n}\n.qlv-props-label {\n    font-size: 11px;\n    font-weight: 600;\n    text-transform: uppercase;\n    letter-spacing: .07em;\n    color: #9ca3af;\n    margin: 0 0 12px;\n}\n.qlv-props-grid {\n    display: grid;\n    grid-template-columns: repeat(3, 1fr);\n    gap: 10px;\n}\n@media (max-width: 540px) {\n    .qlv-props-grid { grid-template-columns: 1fr 1fr; }\n}\n@media (max-width: 360px) {\n    .qlv-props-grid { grid-template-columns: 1fr; }\n}\n.qlv-prop-tile {\n    background: #f9fafb;\n    border: 1px solid #e5e7eb;\n    border-radius: 8px;\n    padding: 12px 14px;\n    display: flex;\n    gap: 10px;\n    align-items: flex-start;\n}\n.qlv-prop-icon {\n    width: 30px;\n    height: 30px;\n    border-radius: 8px;\n    background: #eff6ff;\n    border: 1px solid #dbeafe;\n    display: flex;\n    align-items: center;\n    justify-content: center;\n    flex-shrink: 0;\n}\n.qlv-prop-icon svg {\n    width: 16px;\n    height: 16px;\n    stroke: #2563eb;\n    fill: none;\n    stroke-width: 1.8;\n    stroke-linecap: round;\n    stroke-linejoin: round;\n}\n.qlv-prop-text {}\n.qlv-prop-name {\n    font-size: 12px;\n    font-weight: 600;\n    color: #111827;\n    margin: 0 0 3px;\n}\n.qlv-prop-desc {\n    font-size: 11px;\n    color: #6b7280;\n    line-height: 1.5;\n    margin: 0;\n}\n.qlv-prop-desc code {\n    font-family: \"Courier New\", Courier, monospace;\n    font-size: 10px;\n    background: #efefef;\n    padding: 1px 4px;\n    border-radius: 3px;\n    color: #374151;\n}\n<\/style>\n\n<div class=\"qlv-props\">\n\n    <div class=\"qlv-props-header\">\n        <span class=\"qlv-props-badge\">.qlr<\/span>\n        <p class=\"qlv-props-title\">Layer-level properties parsed<\/p>\n    <\/div>\n\n    <p class=\"qlv-props-label\">Read directly from the QLR file<\/p>\n\n    <div class=\"qlv-props-grid\">\n\n        <div class=\"qlv-prop-tile\">\n            <div class=\"qlv-prop-icon\">\n                <svg viewBox=\"0 0 24 24\">\n                    <circle cx=\"12\" cy=\"12\" r=\"3\"\/>\n                    <path d=\"M12 3v2M12 19v2M3 12h2M19 12h2\"\/>\n                    <path d=\"M5.6 5.6l1.4 1.4M16.9 16.9l1.5 1.5M5.6 18.4l1.4-1.4M16.9 7.1l1.5-1.5\"\/>\n                <\/svg>\n            <\/div>\n            <div class=\"qlv-prop-text\">\n                <p class=\"qlv-prop-name\">Layer opacity<\/p>\n                <p class=\"qlv-prop-desc\">From <code>&lt;layerOpacity&gt;<\/code>. Applied to the map layer and editable via the opacity slider.<\/p>\n            <\/div>\n        <\/div>\n\n        <div class=\"qlv-prop-tile\">\n            <div class=\"qlv-prop-icon\">\n                <svg viewBox=\"0 0 24 24\">\n                    <path d=\"M12 20h9M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4Z\"\/>\n                <\/svg>\n            <\/div>\n            <div class=\"qlv-prop-text\">\n                <p class=\"qlv-prop-name\">Layer name<\/p>\n                <p class=\"qlv-prop-desc\">From <code>&lt;layername&gt;<\/code>. Shown in the layer panel and legend. Editable via the Edit modal.<\/p>\n            <\/div>\n        <\/div>\n\n        <div class=\"qlv-prop-tile\">\n            <div class=\"qlv-prop-icon\">\n                <svg viewBox=\"0 0 24 24\">\n                    <path d=\"M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z\"\/>\n                    <polyline points=\"14 2 14 8 20 8\"\/>\n                    <line x1=\"16\" y1=\"13\" x2=\"8\" y2=\"13\"\/>\n                    <line x1=\"16\" y1=\"17\" x2=\"8\" y2=\"17\"\/>\n                    <polyline points=\"10 9 9 9 8 9\"\/>\n                <\/svg>\n            <\/div>\n            <div class=\"qlv-prop-text\">\n                <p class=\"qlv-prop-name\">Abstract<\/p>\n                <p class=\"qlv-prop-desc\">From <code>&lt;abstract&gt;<\/code>. Displayed in the expandable layer row when present.<\/p>\n            <\/div>\n        <\/div>\n\n    <\/div>\n\n<\/div>\n\n\n\n<h5 class=\"wp-block-heading\"><strong>How glow effects are simulated<\/strong><\/h5>\n\n\n\n<p class=\"wp-block-paragraph\">OpenLayers has no native glow primitive, so outer glow is approximated by stacking five strokes of increasing width and decreasing opacity beneath the main symbol stroke. The spread, blur, and color are all read directly from the QLR&#8217;s <code>effectStack<\/code>. For lines the glow sits on the symbol layer; for polygons it is stored one level up on the renderer itself \u2014 both cases are handled.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Future additions<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">The following \u2014 among others \u2014 are some additions contemplated for the future.<\/p>\n\n\n\n<ul class=\"wp-block-list lista-indentada has-custom-css wp-custom-css-95f578f3\">\n<li>Advanced labels: rule-based labeling, QGIS expression evaluation, label collision avoidance.<\/li>\n\n\n\n<li>Additional symbology: MarkerLine, LinePatternFill, PointPatternFill, FontMarker.<\/li>\n\n\n\n<li>WFS and other OGC service sources in the QLR datasource.<\/li>\n\n\n\n<li>Print \/ export the map as an image or PDF.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<div class=\"wp-block-jetpack-related-posts\">\n<h2 class=\"wp-block-heading has-medium-gray-color has-text-color has-link-color wp-elements-4850faf1e94646f53f24c3b5794f2b37\">Related Posts<\/h2>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>QGIS Layer Viewer is a lightweight, serverless web map viewer that reads QGIS Layer Definition files (.qlr) and GeoJSON data directly in the browser, rendering them on an OpenLayers map with styling that closely matches the original QGIS project \u2014 including categorized and graduated symbology, dash patterns, glow effects, SVG markers, labels, and map tips. &hellip; <a href=\"https:\/\/geo.edesma.org\/blog\/?p=93&#038;lang=en\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &#8220;QGIS Layer Viewer&#8221;<\/span><\/a><\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"wikipediapreview_detectlinks":true,"advanced_seo_description":"","jetpack_seo_html_title":"","jetpack_seo_noindex":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[37,39,41],"tags":[46,54,62,50],"class_list":["post-93","post","type-post","status-publish","format-standard","hentry","category-applications","category-openlayers-en","category-qgis-en","tag-qlr-en","tag-geojson-en","tag-openlayers-en","tag-qgis-en"],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack-related-posts":[{"id":143,"url":"https:\/\/geo.edesma.org\/blog\/?p=143&lang=en","url_meta":{"origin":93,"position":0},"title":"A Bridge Between QGIS and the Web, Built with AI and GIS Expertise","author":"Eduardo Escalona","date":"May 21, 2026","format":false,"excerpt":"Several years ago, I built my first interactive GIS web applications in ActionScript, when Flex still competed on equal footing with other technologies for building rich web applications \u2014 comparable to desktop apps \u2014 including GIS viewers. Later, I migrated to OpenLayers and the HTML\/JS ecosystem. Now, having retired, I\u2026","rel":"","context":"In &quot;AI&quot;","block_context":{"text":"AI","link":"https:\/\/geo.edesma.org\/blog\/?cat=35&lang=en"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/QGISLayerViewer_1.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/QGISLayerViewer_1.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/QGISLayerViewer_1.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/geo.edesma.org\/blog\/wp-content\/uploads\/2026\/05\/QGISLayerViewer_1.png?resize=700%2C400&ssl=1 2x"},"classes":[]}],"_links":{"self":[{"href":"https:\/\/geo.edesma.org\/blog\/index.php?rest_route=\/wp\/v2\/posts\/93","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/geo.edesma.org\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/geo.edesma.org\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/geo.edesma.org\/blog\/index.php?rest_route=\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/geo.edesma.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=93"}],"version-history":[{"count":15,"href":"https:\/\/geo.edesma.org\/blog\/index.php?rest_route=\/wp\/v2\/posts\/93\/revisions"}],"predecessor-version":[{"id":188,"href":"https:\/\/geo.edesma.org\/blog\/index.php?rest_route=\/wp\/v2\/posts\/93\/revisions\/188"}],"wp:attachment":[{"href":"https:\/\/geo.edesma.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=93"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/geo.edesma.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=93"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/geo.edesma.org\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=93"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}