{"id":25703436,"url":"https://github.com/dashpay/grovedbg","last_synced_at":"2026-05-17T05:38:10.556Z","repository":{"id":241131192,"uuid":"802042219","full_name":"dashpay/grovedbg","owner":"dashpay","description":null,"archived":false,"fork":false,"pushed_at":"2024-05-22T14:44:18.000Z","size":583,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-05-22T16:02:50.263Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/dashpay.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-05-17T12:07:26.000Z","updated_at":"2024-08-22T10:20:53.277Z","dependencies_parsed_at":"2024-05-22T16:03:19.948Z","dependency_job_id":"73146685-9d3d-4b56-a508-b3a3c61f3553","html_url":"https://github.com/dashpay/grovedbg","commit_stats":null,"previous_names":["dashpay/grovedbg"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/dashpay/grovedbg","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dashpay%2Fgrovedbg","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dashpay%2Fgrovedbg/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dashpay%2Fgrovedbg/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dashpay%2Fgrovedbg/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dashpay","download_url":"https://codeload.github.com/dashpay/grovedbg/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dashpay%2Fgrovedbg/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33128730,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-16T18:38:32.183Z","status":"online","status_checked_at":"2026-05-17T02:00:05.366Z","response_time":107,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-02-25T05:29:36.628Z","updated_at":"2026-05-17T05:38:10.532Z","avatar_url":"https://github.com/dashpay.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GroveDBG\n_[GroveDB](https://www.grovedb.org/) visualization application_\n\n---\n\n## Accessing GroveDBG\n\n### In the browser\n\nRecent versions of GroveDB include the GroveDBG tool, meaning that if your application uses the GroveDB library with\nthe `grovedbg` feature enabled and has an instance of it, the current application state is easily accessible via your\nweb browser:\n\n```rust\nlet db = Arc::new(GroveDb::open(\"db\")?); // Make sure the handle is `Arc`ed\n\ndb.start_visualizer(10000);\n```\n\nThen, using a WebGL-compatible browser (basically any modern one), navigate to `localhost` with a chosen port. In the\nexample above, it's `localhost:10000`.\n\n### Native app\n\nIn the case of a native app, the GroveDBG frontend is no longer served by GroveDB itself, so this requires the\nGroveDBG code locally. However, this still requires a running GroveDB instance with the `grovedbg` feature and the\n`start_visualizer` call to fetch data from.\n\n```\ngit clone https://github.com/dashpay/grovedbg.git \ncd grovedbg\nGROVEDBG_ADDRESS=http://localhost:10000/ cargo run --release\n```\n\nAs before, this assumes that the GroveDB instance of interest is running locally and the `start_visualizer(port)` call\nused `10000` as the port. It's worth pointing out that the usage of GroveDBG is not limited to local instances and is\nsuitable for remote access as long as all these conditions are met and the port is open for access.\n\n## Usage\n\n### Overview\n\n\u003cdetails\u003e\n  \u003csummary\u003eWhole window screenshot\u003c/summary\u003e\n\n  Don't mind this tiny picture; the details are unnecessary. The goal is to show the vertical division into sections and\n  count them (there should be 6).\n\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/overview_dark.png\"\u003e\n    \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"docs/overview_light.png\"\u003e\n    \u003cimg alt=\"Root subtree with root node fetched.\" src=\"docs/overview_light.png\"\u003e\n  \u003c/picture\u003e\n\u003c/details\u003e\n\nAt the top of the main (and only) GroveDBG window, there is a panel to choose the theme and start a new session. More on\nsessions later, but on launch, it will start a new session automatically, so we can do without this button for now.\n\nThe rest of the window is far more fascinating: 6 vertically divided sections. We'll name them from left to right with a\nbrief description; details will follow later:\n\n#### 1. Profiles\n\nA customizable and persistent subsystem to set up shortcuts, aliases, or default byte representations.\n\n#### 2. Query builder\n\nA recursive form to build any query that GroveDB supports. With buttons at the end of the form, the query can be used to\nfetch data or to fetch a proof.\n\n#### 3. Proof viewer\n\nIf the query builder is used to fetch a proof, it will be shown here. Starting with the root layer, all lower layers can\nbe expanded as well.\n\n#### 4. Merk view\n\nA view of an individual subtree in the form of a merkelized AVL tree. Because trees can be really big, it starts with\nthe root node and provides controls to fetch and show child nodes individually.\n\nIf the query builder was used to fetch a proof and the chosen subtree is one of the proof layers, then the proof data\nwill be shown on top of the Merk view, highlighting the Merkle path with a color.\n\n#### 5. Subtree view\n\nWhile other panels have an arrow on top to hide them, the subtree view is considered the default view and stays visible\nat all times. GroveDB is made of subtrees, and the root subtree is the first thing we'll see on GroveDBG startup.\n\n#### 6. Log\n\nA log window.\n\n### Byte representations\n\nAt its core, GroveDB uses byte key-value tables arranged in hierarchies, making few assumptions about what this data\nmeans. That's why, to make the most of it, GroveDBG is packed with features to ease the use and investigation of data in\nthe most sensible way for the user's domain.\n\nBytes can mean anything, and we give tools to choose how to represent them. By default, GroveDBG uses heuristics to\nchoose the appropriate display for received bytes, but this can easily be overridden.\n\nThis feature is used almost _everywhere_ in the application, which is why we introduce it early. To access it, use\n**right mouse click** on any data (key/value/bytes input).\n\n\u003cdetails\u003e\n  \u003csummary\u003eRoot subtree with display choice menu\u003c/summary\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/root_subtree_dark.png\"\u003e\n    \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"docs/root_subtree_light.png\"\u003e\n    \u003cimg alt=\"Root subtree with root node fetched.\" src=\"docs/root_subtree_light.png\"\u003e\n  \u003c/picture\u003e\n\u003c/details\u003e\n\n**Note on u8 array inputs**: Values are space-separated. For example, to write \"grove,\" you would enter `103 114 111 118 101`.\n\n### Subtree view\n\nThe subtree view is the primary navigation area for GroveDB's structure and remains uncollapsed at all times.\n\n\u003cdetails\u003e\n  \u003csummary\u003eSubtrees example\u003c/summary\u003e\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/subtrees_dark.png\"\u003e\n    \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"docs/subtrees_light.png\"\u003e\n    \u003cimg alt=\"Multiple subtrees\" src=\"docs/subtrees_light.png\"\u003e\n  \u003c/picture\u003e\n\u003c/details\u003e\n\nEach node in this acyclic graph represents an individual subtree within GroveDB. The parent-child relationships are\ndisplayed vertically, with subtrees appearing lower in the hierarchy indicating deeper levels within the HADS. These\nnodes consist of vertically split sections.\n\n**Orange** lines illustrate connections between parents and their respective children. \n\n**Blue** lines represent references, indicating that an item in one subtree is a reference to another item in a\ndifferent subtree. Since this is not a parent-child relationship, arrows are used to make the connection more visually\ndistinct.\n\n\n#### Controls\n\n1. **10** : Fetch the first 10 items of the subtree.\n2. **100** : Fetch the first 100 items of the subtree.\n3. \u003cpicture\u003e\n     \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/button_database_dark.png\"\u003e\n     \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"docs/button_database_light.png\"\u003e\n     \u003cimg alt=\"DB button\" src=\"docs/button_database_light.png\"\u003e\n   \u003c/picture\u003e : Fetch the entire subtree. Be cautious, as this might be too much data.\n4. \u003cpicture\u003e\n     \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/button_fetch_root_dark.png\"\u003e\n     \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"docs/button_fetch_root_light.png\"\u003e\n     \u003cimg alt=\"Fetch root button\" src=\"docs/button_fetch_root_light.png\"\u003e\n   \u003c/picture\u003e : Fetch the subtree's root node. Since the root node key is inherited from the parent, this button may be\n   inaccessible if the fetched part of the parent subtree doesn't include this information.\n5. \u003cpicture\u003e\n     \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/button_clear_dark.png\"\u003e\n     \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"docs/button_clear_light.png\"\u003e\n     \u003cimg alt=\"Clear button\" src=\"docs/button_clear_light.png\"\u003e\n   \u003c/picture\u003e : Clear subtree data to save space.\n6. \u003cpicture\u003e\n     \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/button_query_dark.png\"\u003e\n     \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"docs/button_query_light.png\"\u003e\n     \u003cimg alt=\"Query button\" src=\"docs/button_query_light.png\"\u003e\n   \u003c/picture\u003e : Select this subtree for a path query (more on the query builder later).\n7. \u003cpicture\u003e\n     \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/button_merk_dark.png\"\u003e\n     \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"docs/button_merk_light.png\"\u003e\n     \u003cimg alt=\"Merk button\" src=\"docs/button_merk_light.png\"\u003e\n   \u003c/picture\u003e : Select this subtree for the Merk view to visualize the subtree as a binary tree, which it actually is.\n\n#### Path\n\nComma-separated keys of subtrees starting from the root tree form a path to this subtree. Keys are listed as they appear\nin ancestors, with chosen binary representations and profiles applied. We've already covered binary representations, and\nwe'll cover profiles later.\n\n#### Element*\n\nHorizontally separated sections, each dedicated to a key-value pair in the subtree, with additional controls and\nvariable coloring depending on the element type.\n\nCommon controls include:\n\n1. \u003cpicture\u003e\n     \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/button_refetch_dark.png\"\u003e\n     \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"docs/button_refetch_light.png\"\u003e\n     \u003cimg alt=\"refetch button\" src=\"docs/button_refetch_light.png\"\u003e\n   \u003c/picture\u003e : Re-fetch this element by path and key.\n2. \u003cpicture\u003e\n     \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/button_hash_dark.png\"\u003e\n     \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"docs/button_hash_light.png\"\u003e\n     \u003cimg alt=\"hash button\" src=\"docs/button_hash_light.png\"\u003e\n   \u003c/picture\u003e : Show fetched (unvalidated) hash data.\n\n##### Subtree (orange)\n\nKeys of the subtree representing child subtrees.\n\nControls: \n\n1. **Checkbox** : show/hide the child subtree.\n2. \u003cpicture\u003e\n     \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/button_jump_dark.png\"\u003e\n     \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"docs/button_jump_light.png\"\u003e\n     \u003cimg alt=\"jump button\" src=\"docs/button_jump_light.png\"\u003e\n   \u003c/picture\u003e : Center the subtrees screen on the selected subtree.\n\n##### Item (gray)\n\nA standard key-value pair of bytes, where the interpretation depends on the specific application using GroveDB.\n\n##### Sum Item (dark green)\n\nAn integer value. Although integers could be stored as byte values within the Item variant, Sum Items receive special\nhandling in Sum Trees, which we'll discuss shortly.\n\n##### Sum Tree (green)\n\nA child subtree where the values of all Sum Items within it are added together. As a subtree, it shares the same\ncontrols.\n\n##### Reference (blue)\n\nA reference to a specific key within a particular subtree. By default, it is displayed as an absolute path.\n\nControls:\n\n1. \u003cpicture\u003e\n     \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/button_refdef_dark.png\"\u003e\n     \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"docs/button_refdef_light.png\"\u003e\n     \u003cimg alt=\"refdef button\" src=\"docs/button_refdef_light.png\"\u003e\n   \u003c/picture\u003e : Displays the reference definition along with the resolved absolute path. Most reference types are\n   relative, and these details will be shown if necessary.\n2. \u003cpicture\u003e\n     \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/button_jump_dark.png\"\u003e\n     \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"docs/button_jump_light.png\"\u003e\n     \u003cimg alt=\"jump button\" src=\"docs/button_jump_light.png\"\u003e\n   \u003c/picture\u003e : Navigate directly to the referenced subtree.\n\n#### Pagination controls\n\nThe number of elements shown is limited to 10 per page to ensure predictable node sizes. Arrows are used to navigate\nbetween pages.\n\n### Merk View\n\n\u003cdetails\u003e\n  \u003csummary\u003eMerk view example\u003c/summary\u003e\n\n  \u003cpicture\u003e\n    \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/merk_view_dark.png\"\u003e\n    \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"docs/merk_view_light.png\"\u003e\n    \u003cimg alt=\"Merk view\" src=\"docs/merk_view_light.png\"\u003e\n  \u003c/picture\u003e\n\u003c/details\u003e\n\nAll elements within a subtree are displayed as a list in the subtree view, but this view conceals the actual arrangement\nof the subtrees. This is where the Merk view becomes essential, as it transitions from a simple list of elements to\nthe true binary tree structure. It's important to note that proofs in GroveDB are based on this structure, making the\nMerk view crucial for accurately inspecting proofs.\n\nEach node is shown like the elements in the subtree view, at least in the top part, so there's nothing new to mention.\n\nThe bottom part, below the horizontal line, is related to a received proof, with color coding as follows:\n\n1. **Purple** nodes are subtree elements combined with the latest proof data. Even if the proof only provides a hash,\n   GroveDBG requests the actual data for a clearer view. To avoid confusion, the subtree data is listed at the top of the\n   node, while the proof data is shown below.\n\n2. **Gray** nodes are those that aren't included in proofs and are fetched manually.\n\nThe arrows below are used to fetch the left and right child nodes, respectively.\n\n### Query builder\n\nPath Queries, as we refer to them here, are used to retrieve data from GroveDB, either directly or with cryptographic\nproof. This proof can later be viewed in the Merk view for each subtree involved (referred to as a \"proof layer\") or\nusing a Proof Viewer that we will cover later. For now, let's focus on the Query Builder.\n\nTo create a path query, we need two main components:\n\n1. **Path**: This is selected using the \"Select for Merk\" button located at the top of the desired node in the subtree\n   view.\n2. **Query**: The specific query for the subtree.\n\nAdditionally, an indefinite number of recursive subqueries can be included, allowing for deeper navigation into the\nsubtree hierarchy using paths that are relative to the \"parent\" query.\n\n#### Query\n\nNow that we've covered the path, the query consists of the following elements:\n\n1. **Limit**: Restricts the number of returned elements (data). In the case of a proof, all parts of the Merkle path are\n   still required, but nodes with actual values are limited to this number.\n2. **Offset**: Skips a specified number of elements in the queryset, but this option is not available for proofs.\n3. **Left to Right**: Determines the order of the queryset. For example, if this flag is not set and the limit is 1,\n   only the last item in the queryset will be returned.\n4. **Query Items**: You can add conditions for selecting items in the subtree using the **+** and **-** buttons.\n   Conditions are set with a dropdown, and if an input like a `Key` query item requires additional information, remember\n   that inputs support **byte representations**, meaning the same input can have different interpretations.\n5. **Default Subquery**: When enabled, a default subquery form will be available, which we will discuss shortly.\n6. **Subquery Branches**: A more advanced version of the default subquery, which will also be covered shortly.\n\n##### Default subquery\n\n**For each** subtree item in the queryset, we can apply an additional query by specifying a relative **Path** through\nadding or removing path segment inputs. Each subtree identified in this manner can then have this subquery applied,\nfollowing the same structure as the parent query.\n\n##### Subquery branches\n\nWhile the default subquery is applied to every subtree by appending a relative path, a subquery branch acts as a\nconditional subquery. This means that the top part of this nested form is used to filter the subtrees first, ensuring\nthat the subquery is only applied to those that remain, similar to what was described in the default subquery section.\n\n### Proof Viewer\n\nThe Proof Viewer displays proofs as they are: a series of operations beginning from the root subtree, which is always\nvisible when a proof is available. The lower section, called layers, corresponds to proof layers, with each key being a\none-to-one relationship to child subtrees, functioning recursively. Since every proof must establish a path to the\nroot, the number of layers matches the depth of the requested data.\n\n\u003cpicture\u003e\n  \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/button_merk_dark.png\"\u003e\n  \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"docs/button_merk_light.png\"\u003e\n  \u003cimg alt=\"Merk button\" src=\"docs/button_merk_light.png\"\u003e\n\u003c/picture\u003e: this button can be used to show that part of the proof on Merk view, because keys on those proof layers are\nactually subtrees.\n\n### Profiles\n\nA subsystem designed to set aliases and default byte representations for keys and values.\n\n#### Profiles list\n\nAt the top of the profiles panel, you can select one profile at a time and manage them as follows:\n\n1. **Radio**: Choose the currently active profile.\n2. **Name**: Rename the selected profile.\n3. \u003cpicture\u003e\n     \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/button_copy_dark.png\"\u003e\n     \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"docs/button_copy_light.png\"\u003e\n     \u003cimg alt=\"copy button\" src=\"docs/button_copy_light.png\"\u003e\n   \u003c/picture\u003e: Copy the profile.\n4. \u003cpicture\u003e\n     \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/button_delete_dark.png\"\u003e\n     \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"docs/button_delete_light.png\"\u003e\n     \u003cimg alt=\"delete button\" src=\"docs/button_delete_light.png\"\u003e\n   \u003c/picture\u003e: Delete the profile.\n\n#### Profile Entries list\n\nThe remainder of the profiles panel displays the profile entries, with a **+** button at the end to add another entry\n(available when a non-default profile is selected, as those are read-only).\n\nEach entry initially offers two controls:\n\n1. \u003cpicture\u003e\n     \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/button_edit_dark.png\"\u003e\n     \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"docs/button_edit_light.png\"\u003e\n     \u003cimg alt=\"edit button\" src=\"docs/button_edit_light.png\"\u003e\n   \u003c/picture\u003e: Edit the profile.\n2. \u003cpicture\u003e\n     \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/button_jump_dark.png\"\u003e\n     \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"docs/button_jump_light.png\"\u003e\n     \u003cimg alt=\"jump button\" src=\"docs/button_jump_light.png\"\u003e\n   \u003c/picture\u003e:  Center the subtrees screen on the selected subtree if profile the entry matches any.\n\n#### Profile Entry Editor\n\nOpening a profile editor prvoides even more controls at our displosal:\n\n1. \u003cpicture\u003e\n     \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/button_delete_dark.png\"\u003e\n     \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"docs/button_delete_light.png\"\u003e\n     \u003cimg alt=\"delete button\" src=\"docs/button_delete_light.png\"\u003e\n   \u003c/picture\u003e: Delete the profile entry.\n2. **Alias**: A synonym, with a format that will be explained later.\n3. **Key/Capture**: Defines how this profile entry is matched; this will be covered along with aliases later.\n4. \u003cpicture\u003e\n     \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"docs/button_add_dark.png\"\u003e\n     \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"docs/button_add_light.png\"\u003e\n     \u003cimg alt=\"add button\" src=\"docs/button_add_light.png\"\u003e\n   \u003c/picture\u003e: Add a nested profile entry.\n5. **Value display**: Opens a dropdown to select the default byte representation when an Item is found at a matched\n   location.\n\n##### Key\n\nMatches an element by its name. For example, if this profile entry is applied to the root tree and you enter `32` in the\ninput with the byte representation set to `u8 array`, it will match the element in the root tree with the key `[32]`.\n\nThe **Alias** acts as a literal synonym. So, in the root subtree, the element that was previously under key `[32]` will\nnow appear with the string you specify in the **Alias** field.\n\n##### Capture\n\nUnlike **Key**, this matches all elements. To differentiate between multiple matches, a special syntax `{}` is used in\nthe alias. For example, if you enter `Something {}`, all items in the subtree will have names starting with `Something`,\nwith the actual key inserted where `{}` is. The byte representation of the key is selected using the **Captured Key\nDisplay** dropdown.\n\n##### Nested Entries\n\nProfile entries are recursive, allowing you to match child subtrees of already matched elements, and continue further\ndown the hierarchy. This enables you to create a path to a specific subtree using **Key** entries, or apply changes to\nmultiple nested subtrees more broadly by using **Capture** when appropriate.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdashpay%2Fgrovedbg","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdashpay%2Fgrovedbg","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdashpay%2Fgrovedbg/lists"}