# Dashboard Gallery documentation --- --- > Public gallery of Data Studio dashboards for RUCKUS One and SmartZone: browse redacted examples by vertical or domain, ask about them in plain language, and download an export bundle to import into your own tenant. --- --- # What is the Dashboard Gallery? Source: https://docs.neuralconfig.com/dashboard-gallery/ The Dashboard Gallery is a public collection of **Data Studio dashboards**, published at `https://dashboards.lanpulse.com`. Each one was built against real network telemetry, redacted, and published with the export bundle that recreates it. You can browse them, ask about them in a sentence, and download a bundle to import into your own tenant. There is nothing to install and nothing to sign in to. Every page described in these docs is open to anyone with the URL. ## What you can do with it - **Browse and filter.** The gallery is a grid of dashboards with a filter rail down the side. Filters live in the URL, so a filtered view is a link you can send. See [Browse and filter the gallery](https://docs.neuralconfig.com/dashboard-gallery/browsing/). - **Ask in plain language.** The search box takes a sentence rather than keywords — *"anything on MAC table usage?"* — and answers only from what is published here. See [Ask about the dashboards](https://docs.neuralconfig.com/dashboard-gallery/asking/). - **Download an export bundle.** Every published dashboard has a downloadable ZIP you can import into Data Studio. See [Download an export bundle](https://docs.neuralconfig.com/dashboard-gallery/downloading/). - **Ask for one that isn't there.** If nothing matches, there is a form that puts your request in front of the person who builds them. See [Request a dashboard](https://docs.neuralconfig.com/dashboard-gallery/requesting/). ## Which platforms it covers Data Studio ships in two places, and the gallery names both: | Platform | Export bundle | In the gallery | |---|---|---| | **RUCKUS One** | Yes | Downloadable today | | **RUCKUS AI (SmartZone)** | Not yet | Listed as a disabled control with a *"Coming soon"* note | The unavailable platform is shown rather than hidden, because *"coming soon"* is something you can act on where a missing button is not. The disabled control is not what makes it unavailable — the download route refuses an unavailable platform on the server. See [Download an export bundle](https://docs.neuralconfig.com/dashboard-gallery/downloading/#the-two-platforms). ## What the gallery publishes, and what it doesn't The gallery **publishes two artifacts per dashboard**: a screenshot and a Data Studio export bundle (`dashboard_export_*.zip`). It does not generate either one — both come out of Data Studio itself, which means a signed-in person exports them and uploads them here. What the gallery does is everything that happens after that: redacting the image, scrubbing the bundle, indexing what survives, and serving the result. :::caution[The original is never published] The uploaded screenshot is kept under a private storage prefix and no public route can construct a key into it. The published image is a **new file** with opaque bars burned into it — the covered pixels were never written. See [What is removed before publishing](https://docs.neuralconfig.com/dashboard-gallery/whats-removed/). ::: ## What it is not - **Not a console.** You cannot connect a tenant to it, and nothing you do here reaches your network. - **Not a live view.** Each dashboard is a screenshot taken at a point in time, plus the definition that rebuilds it. Numbers on the image are whatever they were on the day it was captured. - **Not signed in.** There is no reader account, no session and nothing stored about you. The one thing you can write is a dashboard request, and that is covered in [Request a dashboard](https://docs.neuralconfig.com/dashboard-gallery/requesting/). ## Explore the docs - [Browse and filter the gallery](https://docs.neuralconfig.com/dashboard-gallery/browsing/): The card grid, the five kinds of category in the filter rail, shareable filter links, and the per-dashboard permalink. - [Ask about the dashboards](https://docs.neuralconfig.com/dashboard-gallery/asking/): What the plain-language search can answer, why it takes one question at a time, and how a category question returns a whole set. - [Download an export bundle](https://docs.neuralconfig.com/dashboard-gallery/downloading/): Pick a platform, download the ZIP, and import it in Data Studio under Dashboards → Import. - [What is removed before publishing](https://docs.neuralconfig.com/dashboard-gallery/whats-removed/): Destructive image redaction, the fields deleted from the export bundle, and the audit that refuses to store a bundle that still matches a pattern. - [Request a dashboard](https://docs.neuralconfig.com/dashboard-gallery/requesting/): The request form, the duplicate check that runs while you type, and what happens to a request after you send it. - [Limits and quotas](https://docs.neuralconfig.com/dashboard-gallery/limits/): Every rate limit, the daily ceiling on the search's model spend, and what still works once it is reached. - [Public HTTP API](https://docs.neuralconfig.com/dashboard-gallery/api/): The unauthenticated endpoints behind the gallery, with their parameters and response shapes. - [Troubleshooting](https://docs.neuralconfig.com/dashboard-gallery/troubleshooting/): The exact messages the gallery returns, what each one means, and what to do next. Need help? Reach the [support team](https://support.neuralconfig.com/dashboard-gallery?from=docs). --- # Browse and filter the gallery Source: https://docs.neuralconfig.com/dashboard-gallery/browsing/ The gallery is a grid of published dashboards with a filter rail beside it. **Filters live in the URL**, so a filtered view is a link: whatever you select appears as `?facet=` in the address bar, and sending that address sends the selection with it. ## The card grid Each card carries the dashboard's thumbnail, its title, a one-line summary and up to three category chips — the **vertical** it belongs to, followed by up to two **product** chips. The other categories a dashboard carries are on the dashboard itself rather than the card, because a card has room for the two facts people browse by. Clicking a card opens the dashboard without leaving the page, and changes the address to that dashboard's permalink. ## The five kinds of category The rail groups categories by **kind**. There are five, and they fall into two groups: three a person assigns, and two read out of the export bundle at upload. | Kind | Label in the rail | Assigned by | Example values | |---|---|---|---| | `role` | Role | A person | Business leader, Network engineer, Help desk technician | | `vertical` | Vertical | A person | Hospitality, MDU, Higher Ed, K-12, US Federal Government, MWL, Service Provider, LPV, Pro AV | | `product` | Product | A person | Wi-Fi, Switching | | `dataset` | Dataset | Read from the bundle | The Data Studio dataset each chart is built on | | `viz` | Visualization | Read from the bundle | Table, Big number, and the other chart types used | **Role sorts first** because it is the broadest way into the gallery — who a dashboard is for. Every role value returns a real set; a vertical may return a single dashboard. **Dataset and Visualization start collapsed.** They are mechanical, there are many near-identical values, and they are more useful for narrowing a search than for starting one. The rail collapses them because the server marks those kinds as derived, not because their names are special-cased in the page. :::note Categories are data, not code. A new kind or a new value is a row in the gallery's database, and the rail renders whatever the server returns — so the values above are the ones seeded today, not a fixed list. ::: ### A category with nothing behind it is hidden Counts in the rail are over **published** dashboards only, so a category with a count of zero is a dead end and the rail leaves it out. The one exception is a category you currently have selected: dropping that silently out of a link someone sent you would be worse than showing it. ## How selections combine Selections are **ORed within a kind and ANDed across kinds** — the behaviour a filter rail implies. Selecting *Hospitality* and *Higher Ed* shows dashboards in either vertical. Adding *Switching* to that narrows it to dashboards that are in one of those two verticals **and** carry the Switching product tag. Selecting more categories from different kinds can easily land on nothing, and the empty state says so: > No dashboard carries every category selected. Clearing one of them will widen > the results. ## A filter link that no longer resolves shows nothing If a `?facet=` value in a bookmark names a category that no longer exists, the gallery returns **no dashboards** — not the whole unfiltered gallery. A filter that quietly widens into "everything" looks like a working page, which is the worse failure: you would read a full gallery as the answer to a narrow question. The rail names the dead value rather than dropping it in silence: > Some filters in this link no longer exist: `d-sla`. **Remove them** Clicking **Remove** drops just those values and leaves the rest of the selection in place. ## Opening one dashboard Every dashboard has a permalink at `/d/{slug}` — for example `https://dashboards.lanpulse.com/d/rks-sw-l2`. That URL works three ways at once: a person gets the dashboard open over the gallery, a link unfurler gets the dashboard's own title, description and thumbnail, and a crawler gets a real page. A slug that is not published answers `404`, and the gallery renders its own not-found state rather than a bare error. The open dashboard shows: - **The full screenshot**, with **Fit**, **+** and **−** zoom controls stepping through 1×, 1.5×, 2×, 3× and 4×. Double-clicking the image toggles between 1× and 2×, and dragging pans — but only once the image is actually bigger than the frame, so a dashboard that already fits does not move when you drag it. - **The chart count**, beside the title in the top bar. - **The summary and description.** - **Every category it carries**, grouped and headed by kind — so the panel says *Dataset* because the server does. - **"Built on …"** — the internal dataset names, under the friendly labels rather than instead of them. The chip says *Client Info and Statistics* because that is what the Data Studio UI calls it; this line says `binnedSessions` because that is what someone rebuilding the chart has to type. - **The export bundle block** — see [Download an export bundle](https://docs.neuralconfig.com/dashboard-gallery/downloading/). - **Previous** and **Next**, which move through the dashboards currently in the grid. ## What the gallery counts Opening a dashboard reports one **view** for it, and selecting a category reports one selection for that category. These are reader numbers rather than an audited figure, they are never shown publicly, and nothing about you is stored with them — no account, no identifier, no session. ## Next steps - [Ask about the dashboards](https://docs.neuralconfig.com/dashboard-gallery/asking/): When you do not know which category to pick, describe what you need in a sentence instead. - [Download an export bundle](https://docs.neuralconfig.com/dashboard-gallery/downloading/): Take a dashboard you found and import it into your own tenant. - [Public HTTP API](https://docs.neuralconfig.com/dashboard-gallery/api/): The same listing and filtering, as JSON — including every category with its count. --- # Ask about the dashboards Source: https://docs.neuralconfig.com/dashboard-gallery/asking/ The search box at the top of the gallery takes **a sentence, not keywords**. Ask *"anything on MAC table usage?"* or *"which dashboards suit a help desk technician?"* and you get a written answer plus the dashboards it is about, as cards you can open. It answers **only from this gallery**. The model behind it is shown nothing about these dashboards except the rows a search returned, so it has no general knowledge of them to fall back on — and when nothing fits, it says so rather than offering the nearest thing as if it fit. ## What it can answer - **"Is there one for X?"** — the common case, and the one the retrieval is tuned for. - **"What is here for a network engineer?"** — a question about a category. The reply names a few and states the real total, and the cards carry the whole set. See [Category questions return the whole set](#category-questions-return-the-whole-set). - **"Anything on err-disabled ports?"** — a question about a *metric*, which is usually the name of a chart rather than of a dashboard. Chart titles and section headings are read out of each export bundle and indexed, so these land. - **"How many are tagged Wi-Fi?"** — a question about a size. The answer engine is given the real total, not the number of rows it happened to retrieve. Questions are capped at **800 characters**. ## How a question is answered ```mermaid flowchart TB Q["Your question"] --> TOOL["search_dashboards
keywords + optional category"] TOOL --> FTS["Full-text ranking
title, summary, chart titles"] TOOL --> SEM["Semantic ranking"] Q -. "embedded exactly as typed" .-> SEM FTS --> RRF["Reciprocal rank fusion"] SEM --> RRF RRF --> ROWS["Published rows"] ROWS --> REPLY["The written answer"] ROWS --> CARDS["The cards beside it"] ``` Reading that as sentences, because each relationship matters on its own: 1. **Your question goes to a search tool**, never straight to an answer. The model turns it into keywords and an optional category, and calls `search_dashboards`. 2. **Two rankings run over the same candidates.** One is a full-text ranking whose columns are weighted — a dashboard carrying fifteen chart titles must not outrank one whose own title is an exact match. The other compares your question against a stored vector for each dashboard. 3. **Your own sentence is embedded as well as the model's rewrite**, and the two semantic rankings are fused with each other before they meet the full-text half. The words a rewrite drops are often the ones that would have found the row. 4. **Reciprocal rank fusion combines the two halves.** A dashboard has to place well in at least one of them to survive, which is where precision comes from. 5. **Only published dashboards are reachable.** The published check is written into the search's own SQL, again into the query that loads the vectors, and again when the rows are finally read — so a candidate cannot arrive through the vector table and skip it. There is no argument the model can write that reaches an unpublished draft. 6. **The written answer and the cards come from the same rows.** The cards are selected from what the search returned; they are never parsed out of the reply. :::note[Why the cards cannot be wrong] The prompt asks the model not to invent a dashboard. The card selection is what makes it not matter if it does — **a dashboard that does not exist has no row, so it cannot get a card.** Anything you can click on is something the search actually found. ::: ## Every question is a fresh one The endpoint **accepts no conversation history**. It is not validated and rejected — it is simply never read. Anyone can post any body to a public endpoint, and a forged previous *answer* is indistinguishable from one this site really produced, which would make every rule about what may be asserted negotiable. So the box takes one question and answers it, and the interface matches: one answer on screen, replaced by the next. Asking a follow-up means asking a whole question — *"and which of those is for switching?"* has nothing to refer back to. ## Category questions return the whole set Asking what a category contains is a question about a **set**, so a category search returns the entire tagged set rather than the first few. Two things follow: - **The reply states the real total.** It names a few of them in prose and tells you how many there are. Before the total was available, the answer engine reported the number of rows it had retrieved — five — as though five were the answer, when sixteen matched. - **Every one of them still gets a card**, even where the prose names three. The cards are how you reach the rest of the set. When an answer's cards are only part of a category, a chip appears under them: > **Show all 16 in the gallery →** It appears only when there is a rest to show — if the cards already are the whole category, there is nothing to offer. The point of it is the **URL**: an answer has no address, and a filtered gallery is a link you can send. ## What you see while it works A question takes a few seconds, and the panel reports what is happening rather than showing a bare spinner: which search is running, the terms it is running, and how much matched. The answer itself arrives once, at the end. ## Limits worth knowing | Limit | Value | |---|---| | Question length | 800 characters | | Searches per question | 3 | | Model turns per question | 4 | | Wall clock for one model call | 40 seconds | | Answer length | 1,200 tokens | | Questions per minute, per address | 20 | Two different models answer, depending on how much of the day's budget is left — they were measured as equal on recall, so the swap costs precision rather than coverage. Once the day's allowance is spent the box stops answering and says so, and everything else on the site keeps working. Both are covered in [Limits and quotas](https://docs.neuralconfig.com/dashboard-gallery/limits/). :::tip[When search is resting, the filters are not] The category rail and the dashboards themselves have nothing to do with the model. If the search box is unavailable, filtering still finds the same dashboards — see [Browse and filter](https://docs.neuralconfig.com/dashboard-gallery/browsing/). ::: ## Next steps - [Request a dashboard](https://docs.neuralconfig.com/dashboard-gallery/requesting/): When the honest answer is that nothing here fits, the answer panel offers to pass the request on. - [Limits and quotas](https://docs.neuralconfig.com/dashboard-gallery/limits/): The daily ceiling on model spend, what happens past it, and every rate limit. - [Troubleshooting](https://docs.neuralconfig.com/dashboard-gallery/troubleshooting/): The exact sentences the search returns when it refuses, and what each one means. --- # Download an export bundle Source: https://docs.neuralconfig.com/dashboard-gallery/downloading/ Every published dashboard can be downloaded as a **Data Studio export bundle** — a ZIP of YAML documents — and imported into your own tenant. The download needs no sign-in and no request: open a dashboard and the bundle is in the panel beside it, under **Export bundle**. ## The two platforms Data Studio ships in two places, and the panel lists both: | Platform | Control | Why | |---|---|---| | **RUCKUS One** | A live download link | It has an export bundle format | | **RUCKUS AI (SmartZone)** | A disabled button reading *"Coming soon — the converter is being written"* | RUCKUS AI has no bundle format of its own, so the shape a converter would emit is not yet settled | The unavailable platform is **listed rather than hidden**, because "coming soon" is information you can act on where a missing button is not. :::note[The disabled button is not what makes it unavailable] The download route resolves the platform through the same registry the panel reads and answers `404` for one that is not available — on the server, before anything is read from storage. The gallery's pages are static files served to anyone who asks for them, so a disabled control could never be the thing deciding this. ::: ## Download and import 1. **Open the dashboard** you want, from the grid or from its `/d/{slug}` permalink. 2. **Click the platform button** under *Export bundle*. The file arrives named after the dashboard's slug — `rks-sw-l2-export.zip`. 3. **In Data Studio, go to `Dashboards → Import`** and choose the ZIP. 4. **Open the imported dashboard.** Its charts bind to your own datasets and render against your own data. ## What has already been done to the bundle The file you download has been through two separate operations, and knowing which is which explains what you will see after importing. **Scrubbed once, when it was uploaded.** Identity fields are deleted, filters pinned to tenant-scoped columns are dropped, and values with a recognisable shape — MAC addresses, IP addresses, hostnames, emails, serial numbers — are replaced with values from reserved documentation ranges. A bundle that still matches a pattern after that is never stored at all. The full account is in [What is removed before publishing](https://docs.neuralconfig.com/dashboard-gallery/whats-removed/). **Re-identified on every download.** Each download gets a **fresh set of dashboard and chart identifiers**. Dataset and database identifiers are left exactly as they were. ### Why the identifiers are fresh every time An import matches objects **by identifier, and those identifiers match globally across tenants** — not just within one. If two people imported byte-identical copies of the same bundle, the second import would not create a second dashboard; it would update the first person's record and move its tenant scoping to the importer. So no two downloads of the same dashboard carry the same dashboard and chart identifiers. One old-to-new map is built for the whole archive and then applied across every file, which is what keeps a layout block pointing at the charts it names. The response is sent `no-store` for the same reason: a cached copy handed to a second downloader would reintroduce the exact collision this prevents. **Dataset and database identifiers are deliberately excluded from that map.** They are how the import binds to a real dataset, so they must survive both operations unchanged. ## What to expect after importing | You will see | Why | |---|---| | The dashboard's layout, charts and sections, intact | Structure is not sensitive and is not touched | | Charts rendering against **your** data | Filters pinned to tenant-scoped columns such as `zoneName`, `ssid` and `apName` were removed rather than rewritten — a rewritten value would match no real row and the chart would render empty | | Venue or site names still in chart *titles* and text | A name like *"Riverside"* or *"Home"* is an ordinary word with no shape a pattern can catch. These are reviewed by a person before publishing rather than caught by a rule | | Documentation-range values in descriptions | `00:00:5e:00:53:01`, `192.0.2.4`, `host-1.example.com` and similar are replacements, not real values | | Filter **dropdowns** on tenant-scoped columns still present | A dropdown control is part of the dashboard's structure, so it survives; only its pre-selected default is cleared | :::caution[Datasets are referenced, not included] The bundle carries no `datasets/` or `databases/` directory — datasets are referenced by identifier only. The import binds to a dataset that already exists in your tenant. If the dataset a chart names is not there, that chart has nothing to bind to. ::: ## URLs The canonical download URL is the bare one, and it means RUCKUS One: ``` https://dashboards.lanpulse.com/d/{slug}/download ``` The per-platform form resolves to the identical bytes for the default platform: ``` https://dashboards.lanpulse.com/d/{slug}/download/ruckus-one ``` Both are rate limited to **20 downloads per minute per address**, and both refuse a dashboard that is not currently published. See [Public HTTP API](https://docs.neuralconfig.com/dashboard-gallery/api/#get-dslugdownloadplatform). ## Next steps - [What is removed before publishing](https://docs.neuralconfig.com/dashboard-gallery/whats-removed/): Exactly which fields are deleted, which filters are dropped, and the audit that gates the write. - [Browse and filter the gallery](https://docs.neuralconfig.com/dashboard-gallery/browsing/): Find the dashboard whose bundle you want, by role, vertical, product or dataset. - [Troubleshooting](https://docs.neuralconfig.com/dashboard-gallery/troubleshooting/): A download that 404s, a 429, and what an empty imported chart means. --- # What is removed before publishing Source: https://docs.neuralconfig.com/dashboard-gallery/whats-removed/ Each dashboard reaches the gallery as two artifacts — a screenshot and a Data Studio export bundle — and both are rewritten before anything is published. The rule the whole design is built around is short: **An unredacted original is never publicly reachable.** That is enforced in the API rather than in the page. The gallery's own pages are static files served to anyone who asks for them, so they can never be the thing deciding what is allowed. ## The publish pipeline ```mermaid flowchart TB UP["Upload
screenshot + export bundle"] --> PRIV["Private storage
originals, never served"] PRIV --> OCR["OCR proposes rectangles"] OCR --> REVIEW["A person reviews them"] REVIEW --> FLAT["Flatten to a new image file"] PRIV --> SCRUB["Scrub the bundle"] SCRUB --> AUDIT["Re-scan what was just written"] AUDIT -->|"clean"| PUB["Public storage"] AUDIT -->|"still matches"| STOP["Nothing is written"] FLAT --> PUB ``` In sentences: the upload goes to **private storage**, where nothing public can reach it. The image is redacted by OCR proposing rectangles, a person reviewing them, and the browser flattening the result into a **new file**. The bundle is scrubbed and then **audited by re-scanning what the scrubber just wrote** — if the audit still finds a match, nothing is written to public storage at all. Only the flattened image and a clean bundle reach the public side. ## The image: redaction is destructive **Every bar in a published screenshot covers pixels that were never written into the file.** The published image is not the original with rectangles drawn over it — it is a new image, drawn to a canvas with opaque rectangles filled in and saved. There is nothing underneath a bar to uncover. Bars are **opaque, not blurred**. Blur on small text is a weaker guarantee than it looks. The detection step runs **in the browser**, and the OCR engine is served from the gallery's own origin rather than a CDN — the unredacted image never leaves the machine it was opened on. Each recognised word is checked against the same pattern set the bundle scrubber uses, and a match becomes a *proposed* rectangle that a person accepts, moves, resizes or deletes. Running detection again only **adds** proposals; it never removes a bar placed by hand. ### Publishing with no bars at all Some screenshots genuinely have nothing to cover, so publishing with zero rectangles is allowed — but only after a second confirmation, recorded explicitly. To publish, a dashboard needs a flattened image **and** either at least one rectangle or that explicit record. The rectangles are **counted**, not merely checked for: an editor run that covered nothing still saves an empty list, and a list existing is not evidence that anything was covered. ### What stays private - **The original screenshot**, under a storage prefix that the code serving public assets cannot construct a key into. - **The rectangle coordinates.** They are kept only so a redaction can be reopened and adjusted, and are never used to render a public view. - **The scrub report** (below). ## The bundle: scrubbed once, on upload Redacting only the screenshot would publish the same data in plain YAML — the export carries tenant identifiers, owner identifiers, owner email addresses and hardcoded filter values. So the bundle is rewritten too. ### Identity fields are deleted, not replaced An import assigns ownership to whoever runs it, so there is nothing left for these to do. A pseudonymised owner id would be a lie the importer then has to notice. `tenant_ids` · `tenant_id` · `owner_ids` · `owners` · `created_by` · `changed_by` · `created_by_fk` · `changed_by_fk` · `last_saved_by` · `email` · `username` · `user_id` · `certified_by` · `certification_details` ### Filters on tenant-scoped columns are dropped Some columns hold tenant data **whatever value they contain**. A venue named "Home" is an ordinary English word that no shape-based rule can find, so these clauses are matched on the **column name** instead, and the whole clause is removed: `zoneName` · `venueName` · `venue` · `zone` · `ssid` · `networkName` · `wlanName` · `apName` · `apMac` · `apGroupName` · `apSerialNumber` · `clientMac` · `clientIp` · `userName` · `userId` · `deviceName` · `hostname` · `serialNumber` · `switchName` · `switchMac` · `tenantId` · `tenantName` · `accountName` · `customerName` Matching is case-insensitive, because bundles are inconsistent about `zoneName` versus `zonename`. :::note[Dropped rather than pseudonymised, and that is deliberate] A pseudonymised comparator would still be a value — just one matching no real dimension value. The chart would import cleanly and render **empty**, which is harder to notice than a filter that is plainly gone. Every drop is recorded in the report so a person reviews it. A filter **dropdown control** on one of these columns is different: it is part of the dashboard's structure, so it survives, and only its pre-selected default is cleared. ::: ### Values with a shape are replaced Remaining strings are checked against the same pattern set the screenshot editor uses. Each distinct real value maps to the same replacement every time, so a filter still matches the chart beside it. | What is matched | Replaced with | Range | |---|---|---| | MAC address | `00:00:5e:00:53:xx` | RFC 7042 documentation block | | IPv4 address | `192.0.2.x` | RFC 5737 TEST-NET-1 | | IPv6 address | `2001:db8::x` | RFC 3849 documentation prefix | | Email address | `user1@example.com` | Reserved example domain | | Hostname / FQDN | `host-1.example.com` | Reserved example domain | | UUID / tenant id | `00000000000000000000000000000000` | — | | Serial number | `SERIAL000001` | — | Replacements are **shaped like what they replace** rather than being `[REDACTED]`, for two reasons. A filter whose comparator became `[REDACTED]` would import cleanly and then render nothing. And because they keep their shape, the audit re-finds them all — which is how "scrubbed correctly" is told apart from "still leaking". :::caution[Serial numbers must carry a letter as well as a digit] This is a deliberate under-match. Without the letter requirement, the pattern matched the `1000000000` inside a bytes-to-GB divisor across ten charts of a real bundle and rewrote it into `SERIAL000001` — valid YAML, broken arithmetic, and no error until a person opened the chart. All-numeric serials are therefore not detected. Under-matching surfaces in the editor for a person to fix; over-matching silently corrupts a chart definition nobody re-reads. ::: ### Two places that are easy to miss, and are not missed - **The nested copy.** One chart field holds a JSON document inside a YAML string, carrying a second copy of the chart's parameters and filters — tenant identifiers included. It is parsed, scrubbed by the same rules and written back. A scrubber that walked the YAML tree alone would publish that copy intact. - **The dialect.** Files are re-serialised as **YAML 1.1**, which is what the importer reads. A default YAML 1.2 writer leaves unquoted precisely what a 1.1 reader retypes: an exported timestamp comes back as a *date* rather than a string, and the importer rejects the whole archive before reading a single chart. The same gap turns `yes`/`no`/`on`/`off` into booleans and `10:30:00` into a number. ### The audit refuses the write The archive the scrubber just wrote is re-opened and scanned again over its raw text. Replacement values are recognised as replacements rather than flagged again. **If anything else still matches a pattern, nothing is written to public storage at all** — storing it and relying on a published check to keep it unreachable would put a leaking object in the public namespace with one query between it and the world. ### The report, and what only a person can catch The report lists every removed field, every dropped filter with the value it held, every real-to-replacement pair, and any file that could not be inspected. It stays with the record and is **never published**. It is read before the dashboard is, because some things no rule here can find: a venue name, a network name or a site label sitting in a chart title or a block of prose. Those have no shape, and the read is what catches them. ## Why the boundary holds | Mechanism | What it prevents | |---|---| | Two storage prefixes — originals private, published artifacts public | Nothing public shares a namespace with an original | | Asset URLs take an id, a revision and one of three fixed filenames | There is no input that can address an object outside the public namespace | | Every public query bakes `status = 'published'` into its SQL | A route cannot forget to filter for published-ness | | Only the revision a record currently points at is served | A superseded, *less* redacted revision cannot be reached by guessing the previous number | | Public responses list what goes out rather than deleting what must not | A new column is private until someone decides otherwise | That last row is why original keys, the scrub report and the rectangle coordinates are absent from every public response: they were never added to the list of things that go out. ## Next steps - [Download an export bundle](https://docs.neuralconfig.com/dashboard-gallery/downloading/): What the scrubbed bundle looks like once it is imported, and why its identifiers change on every download. - [Public HTTP API](https://docs.neuralconfig.com/dashboard-gallery/api/): What a public response actually contains, field by field. - [What is the Dashboard Gallery?](https://docs.neuralconfig.com/dashboard-gallery/): Where the two artifacts come from, and what the gallery does and does not generate. --- # Request a dashboard Source: https://docs.neuralconfig.com/dashboard-gallery/requesting/ When nothing in the gallery fits, you can describe what you need and the gallery will pass it on. This is the **only thing on the site a visitor can write**, and it needs no account. ## Where the form is There is no standing "Request a dashboard" button, and that is deliberate: the form appears at the moment you are already holding the thought. - **Under a search answer.** When the search tells you the nearest thing it has, the offer to request one is right there, and the form opens with your question already in it. - **On an empty grid.** When a filter combination returns nothing, the empty state offers it. - **At `#request`** on the gallery URL, which opens it with an empty field. It opens **in place, under the header** — directly below the answer you are deciding against — rather than as a dialog over it. A dialog would hide the very answer you were reading. ## What the form asks for | Field | Required | Limits | |---|---|---| | **What do you want on it?** | Yes | 10 to 1,200 characters | | **Email** | No | Up to 254 characters, and it must look like an address | The description is the whole of it. Naming the metric, the audience and the question the dashboard should answer is what makes a request buildable — the placeholder shows the shape: > *Roaming failures by AP, so I can see which radios clients keep falling off.* The email address is optional and exists only so the request can be answered. A request with no address is a perfectly good request. ## Two things that happen while you type **A duplicate check.** Once you have typed enough, the gallery runs your half-written sentence through its own search and shows up to **three** dashboards that may already cover it. It is the same retrieval the search box uses, minus the model — so it costs nothing and takes no time worth noticing. If it fails for any reason it shows nothing at all: a duplicate check that could stop you asking for a dashboard would have inverted its own purpose. When you reached the form from a search answer, the check does not re-run immediately — the answer above **is** the duplicate check for that sentence. It starts once you have changed enough of the draft for it to be your own question rather than the one you arrived with. **One clarifying question.** Once the draft reaches about 40 characters, the gallery may ask a single question about it — the one thing that would most help whoever builds it. Answering appends your answer to the draft. It is entirely optional: > *Or ignore this — the request sends either way.* If the day's model allowance is spent, or anything else goes wrong, no question appears and the form is unaffected. ## The bot check Submitting requires a **Cloudflare Turnstile** check, verified on the server against Cloudflare rather than taken from the page's word for it. The widget loads **only when the form is opened**, so a visitor who never asks for a dashboard never fetches a bot-detection script. It is the one third-party script on the public site, and it is loaded from Cloudflare rather than served from this origin — the script *is* the verification, so a local copy would mint tokens Cloudflare then rejects. :::note A Turnstile token verifies exactly once and is good for five minutes. If a submission is refused, the widget resets so your next attempt gets a fresh token — otherwise the second try would be a guaranteed failure. ::: The rate limit in front of the form — **6 submissions per minute per address** — is a smoother, not the check. Turnstile is the check. ## After you send it You get a confirmation and nothing else: > **That is in the queue to be built.** - **The request is never public.** There is no endpoint that reads requests back — not even for the person who wrote it. Your words and your address are the only things in this gallery that were *given* rather than published, and the only route that can see them is behind the admin sign-in. - **It arrives with the status `new`.** Only the site owner can move it on, to `planned`, `built` or `declined`. - **"N in the queue"** beside the dashboard count is the number of requests at **`planned`** — reviewed and accepted for building. It is deliberately not the number submitted, because anyone can submit and nobody but the owner can promote. The segment is absent entirely when the number is zero, and it disappears while a filter is applied, since the queue does not respond to filters. ## If the form is not there The gallery **hides the form when the bot check is not configured**, rather than showing a form that cannot succeed. The server refuses independently either way, so a form that appears is one that can work. ## Next steps - [Ask about the dashboards](https://docs.neuralconfig.com/dashboard-gallery/asking/): Check whether the thing you are about to request already exists — the search is the fastest duplicate check there is. - [Limits and quotas](https://docs.neuralconfig.com/dashboard-gallery/limits/): The character limits, the submission rate limit, and the model allowance behind the clarifying question. - [Troubleshooting](https://docs.neuralconfig.com/dashboard-gallery/troubleshooting/): A refused verification, a request that is too short, and a form that will not appear. --- # Limits and quotas Source: https://docs.neuralconfig.com/dashboard-gallery/limits/ Every limit that can change what the gallery does, in one place. Most readers never meet any of them; the one worth understanding in advance is the daily model allowance behind the search box, because it is the only limit whose effect lasts longer than a minute. ## Rate limits All of these are **per client address, per minute**, and all of them return a plain sentence rather than a silent failure. | What | Limit | On refusal | |---|---|---| | Questions to the search box | **20 / minute** | `429` — *"Too many questions in a row — give it a minute."* | | Dashboard requests | **6 / minute** | `429` — *"That is a lot of requests in a row — give it a minute."* | | Bundle downloads | **20 / minute** | `429` — *"Too many downloads in a row — give it a minute."* | | View beacons | **60 / minute** | `429` with an empty body | The duplicate check and the clarifying question on the request form share the request limit. Neither returns an error when refused — the duplicate check shows no cards and the clarifier shows no question, because both are asides beside a form that works without them. :::caution[These are smoothers, not accounting] Cloudflare documents the rate limiting binding as *"intentionally designed to not be used as an accurate accounting system"* — its counters are per-location and converge asynchronously. Measured against this site, it let **65 requests from one address through in a minute without a single refusal**. That is fine for what it is for. It is not a spending limit, which is why the spending limit is a separate mechanism. ::: ## Content limits | Where | Limit | |---|---| | A question to the search box | 800 characters | | A dashboard request | 10 to 1,200 characters | | An email address on a request | 254 characters | | Draft length before a clarifying question is offered | 40 characters | | Dashboards per API listing page | 60 by default, 100 maximum | | Results the duplicate check shows | 3 | ## The answer engine's own caps | Limit | Value | What happens at it | |---|---|---| | Searches per question | **3** | The search tool is **withheld**, not merely discouraged, and the model is told to answer from what it already has | | Model turns per question | **4** | The turn budget ends and the reply is written | | Wall clock for one model call | **40 seconds** | The call is aborted and the question returns a `503` | | Answer length | **1,200 tokens** | The reply is cut. Citations are written last, and the gallery keeps whatever was written before the cut | | Results from one search | 1 to 12, default 5 | — | | Results from a **category** search | The whole tagged set, up to 60 | A question about a category is a question about a set, so it is not cut to the default | ## The daily model allowance The search box is unauthenticated and calls a language model, which means an unmetered visitor could write the account's inference bill. So there is a hard ceiling on what all of the day's questions together may spend. | | | |---|---| | **The ceiling** | **$1 per UTC day** | | In Cloudflare's unit | About **90,900 neurons**, at the published rate of $0.011 per 1,000 | | A measured question | About **18 neurons** | | Questions that buys | Roughly **1,230 per day** | | Checked | Before the model runs | | Recorded | After it runs, whether it succeeded or not | The unit is the **neuron** because that is what Cloudflare bills and what each completion reports back — so the ledger is a record of money rather than an estimate from token counts, and it stays true across a price change or a model swap. ### Why 1,230 questions rather than 780 Two models answer, and which one you get depends on how much of the day is left: | | Model | When | |---|---|---| | **Primary** | DeepSeek v4 Flash | Until **75%** of the day's allowance is spent | | **Economy** | GLM 4.7 Flash | For the remaining 25% | Over a 30-question set they scored **the same on recall** — each found every dashboard it should have, and each refused every question the gallery has no answer for. So the choice was never about coverage. DeepSeek is more precise (95% against 85%) and far steadier at the slow tail (11.8 seconds at the 95th percentile against 32.3); GLM costs about a third as much to run. Taking both means the allowance buys **~583 DeepSeek questions and then ~650 GLM ones** instead of 780 DeepSeek ones, and the end of a busy day degrades to a slightly less precise answer rather than to no answer. Which model runs is read once per question, from the same spend figure the ceiling check already fetched — so the two cannot disagree, and one question is answered by one model the whole way through. ## What happens once the allowance is spent The search box returns a `429` and says so: > Search has used up today's allowance and is resting until tomorrow — the > filters below still work. **Everything that is not the model keeps working.** The categories, the filter rail, every dashboard, every permalink and every download are unaffected, and the duplicate check on the request form drops to text-only matching rather than refusing. The degraded state is the site minus one feature, not a broken page. The allowance resets at **00:00 UTC**. :::note[The ledger counts failures too] What a call consumed is recorded in a `finally` block, so a question that timed out or failed still counts against the day. A ledger that counted only successes would be one you walk past by making the model fail. ::: ## Caching | Resource | Policy | |---|---| | Dashboard images and thumbnails | Immutable for one year — a tightened redaction publishes at a new revision, so the old URL is simply never requested again | | A dashboard permalink's HTML | 60 seconds, then revalidated | | The sitemap | 10 minutes | | **An export bundle** | **`no-store`** — never cached, because two downloaders must not receive the same identifiers | ## Next steps - [Ask about the dashboards](https://docs.neuralconfig.com/dashboard-gallery/asking/): What the search does with a question before any of these caps apply. - [Public HTTP API](https://docs.neuralconfig.com/dashboard-gallery/api/): Which endpoint each of these limits sits in front of. - [Troubleshooting](https://docs.neuralconfig.com/dashboard-gallery/troubleshooting/): Telling a rate limit apart from a spent allowance — both are a 429. --- # Public HTTP API Source: https://docs.neuralconfig.com/dashboard-gallery/api/ The gallery's own pages are built on a public, unauthenticated JSON API. There is no key to obtain and no sign-in, and every endpoint here is subject to the limits in [Limits and quotas](https://docs.neuralconfig.com/dashboard-gallery/limits/). Base URL: `https://dashboards.lanpulse.com` | Endpoint | Method | What it does | |---|---|---| | [`/api/dashboards`](#get-apidashboards) | `GET` | List published dashboards, optionally filtered | | [`/api/dashboards/{slug}`](#get-apidashboardsslug) | `GET` | One published dashboard | | [`/api/facets`](#get-apifacets) | `GET` | The category taxonomy, with published counts | | [`/api/chat`](#post-apichat) | `POST` | Ask a plain-language question | | [`/api/requests`](#post-apirequests) | `POST` | Submit a dashboard request | | [`/api/requests/similar`](#post-apirequestssimilar) | `POST` | The duplicate check | | [`/api/requests/clarify`](#post-apirequestsclarify) | `POST` | One clarifying question about a draft | | [`/api/dashboards/{slug}/view`](#post-apidashboardsslugview) | `POST` | The view beacon | | [`/d/{slug}/download/{platform}`](#get-dslugdownloadplatform) | `GET` | The export bundle | | [`/assets/{id}/{rev}/{file}`](#get-assetsidrevfile) | `GET` | Images and stored bundles | **Only published dashboards are reachable through any of them.** The published check is written into the SQL of every query rather than applied by whatever calls it. ## GET /api/dashboards Lists published dashboards, newest publication first. | Parameter | Type | Default | Notes | |---|---|---|---| | `facet` | string, repeatable | — | A category id. Repeat it to select several; values are ORed within a kind and ANDed across kinds | | `limit` | number | `60` | Capped at `100` | | `offset` | number | `0` | Negative values are treated as `0` | ``` GET /api/dashboards?facet=r-network-engineer&facet=d-switching&limit=20 ``` Returns `{ "dashboards": [ … ] }`. Each entry is the same shape everywhere it appears in this API: | Field | Type | Notes | |---|---|---| | `slug` | string | The permalink segment — `/d/{slug}` | | `title` | string | | | `summary` | string \| null | | | `description` | string \| null | | | `image` | string | Path to the full redacted screenshot | | `thumb` | string | Path to the thumbnail | | `download` | string | The canonical RUCKUS One bundle path | | `downloads` | array | One entry per platform — `{ id, label, available, note?, href }`, with `href` null when unavailable | | `image_w`, `image_h` | number \| null | Pixel dimensions of the full image | | `chart_count` | number \| null | Charts read out of the bundle | | `viz_types` | string[] | Chart types used | | `datasets` | string[] | Internal dataset **names** — the identifiers stay server-side | | `facets` | array | `{ kind, label, slug }` per category | | `published_at` | number \| null | Epoch milliseconds | :::note[An unresolvable filter returns nothing, not everything] If a `facet` value names no category, the response is an empty list. It is never the whole unfiltered gallery — a filter that quietly widens is the more dangerous failure, because a full response looks like a working page. ::: ## `GET /api/dashboards/{slug}` One dashboard, in the shape above, as `{ "dashboard": { … } }`. A slug that is not published returns `404` with `{ "error": "not found" }`. ## GET /api/facets The whole category taxonomy, plus the configuration the gallery's page needs before it paints. ```json { "kinds": [ { "kind": "role", "label": "Role", "sort": 5, "derived": false } ], "facets": [ { "id": "r-network-engineer", "kind": "role", "label": "Network engineer", "slug": "network-engineer", "count": 10 } ], "suggestions": [ "…" ], "examples": [ "…" ], "demos": [ { "slug": "…", "prompt": "…" } ], "requests": { "enabled": true, "site_key": "…", "planned": 3 } } ``` - **`count` is over published dashboards only**, so a category with a count of zero has nothing public behind it. - **`derived` marks the kinds read out of an export bundle** — `dataset` and `viz` — rather than assigned by a person. The gallery collapses those groups in its rail from this flag rather than from a list of kind names in the page. - **`requests.planned`** is the number of requests accepted for building. It is the only public read of the request table there is. ## POST /api/chat Ask a question in plain language. ```json { "message": "which dashboards suit a help desk technician?" } ``` | Field | Required | Notes | |---|---|---| | `message` | Yes | 1 to 800 characters | **A `history` field is never read.** It is not validated and rejected — there is simply no path by which a conversation could reach the model. Every request is a single fresh turn. The default response is JSON: ```json { "reply": "…", "dashboards": [ /* the same dashboard shape as above */ ], "filter": { "id": "d-switching", "label": "Switching", "count": 16 } } ``` `filter` is the category the answer's dashboards all share, with the number that carry it — or `null`. It is present only when *every* returned dashboard carries the category, since one question may search several. Sending `Accept: application/x-ndjson` returns progress instead: one JSON object per line, with `t` set to `turn`, `search` or `results` as the work happens, and a final `answer` line carrying the same three fields. An `error` line replaces it on failure. | Status | Meaning | |---|---| | `400` | Empty message, over 800 characters, or an unparseable body | | `429` | Rate limited, **or** the day's model allowance is spent — the message says which | | `503` | The model was unavailable or the call timed out | ## POST /api/requests Submit a dashboard request. **This is the only public write that stores text you typed**, and the only one with a bot check. ```json { "body": "Roaming failures by AP…", "email": "you@example.com", "token": "…" } ``` | Field | Required | Notes | |---|---|---| | `body` | Yes | 10 to 1,200 characters | | `email` | No | Up to 254 characters, shape-checked | | `token` | Yes | A Cloudflare Turnstile token, verified server-side | Returns `201` with `{ "ok": true, "id": "…" }`. The id is all you get back — **there is no endpoint that reads a request**, so there is nothing to fetch it with. | Status | Meaning | |---|---| | `400` | Too short, too long, or a malformed email address | | `403` | The Turnstile verification did not pass | | `429` | Rate limited | | `503` | The bot check is not configured — the endpoint fails closed | The body is validated **before** the token is verified, because a token verifies exactly once: refusing a too-short request afterwards would leave you holding a spent token and a form you cannot resubmit. ## POST /api/requests/similar The duplicate check. Runs the gallery's own retrieval over a draft — no model call. ```json { "query": "roaming failures by AP" } ``` Returns `{ "dashboards": [ … ], "total": n }`, at most **3** dashboards. A query under 10 characters returns an empty list, and so does any failure: this endpoint never reports an error to the page, because a duplicate check that blocks a form has inverted its own purpose. ## POST /api/requests/clarify Asks one question about a request draft. ```json { "draft": "Roaming failures by AP…" } ``` Returns `{ "question": "…" }`, or `{ "question": null }` when the draft is under 40 characters, the day's model allowance is spent, the caller is rate limited, or anything at all goes wrong. ## `POST /api/dashboards/{slug}/view` The view beacon. No body is read; the slug is in the path. Returns `204`. A slug that is not published returns `404`, so a counter can only ever name something the gallery actually publishes. It is ungated on purpose — no gate makes a client-reported counter unforgeable without putting a bot-detection script on every dashboard open, which is a cost every reader would pay to protect a number nobody bills against. ## `GET /d/{slug}/download/{platform}` The export bundle. The bare `/d/{slug}/download` means `ruckus-one` and is the canonical URL. | Platform | Available | |---|---| | `ruckus-one` | Yes | | `ruckus-ai` | No — returns `404` | Responds with `application/zip`, `Content-Disposition: attachment`, and `Cache-Control: no-store`. **Every response is different**: dashboard and chart identifiers are regenerated per request, while dataset and database identifiers are preserved. An unknown platform, an unknown slug, an unpublished dashboard and a dashboard with no stored bundle all return `404`. ## `GET /assets/{id}/{rev}/{file}` Serves a published dashboard's artifacts. `file` is one of `full.webp`, `thumb.webp` or `export.zip`; anything else is a `404`. The route never accepts a storage key — it takes an id, a revision and one of those three filenames and constructs the key itself, so there is no input that can address anything outside the public namespace. It serves only assets belonging to a **currently published** dashboard, and only at the revision that record currently points at: an earlier revision number is a `404`, because the reason a redaction gets tightened is that the previous one covered too little. Responses are cached immutably for one year. ## Other public paths | Path | | |---|---| | `/sitemap.xml` | The gallery, the how-it-works page and every published permalink | | `/robots.txt` | Allows everything except `/admin` | ## Next steps - [Limits and quotas](https://docs.neuralconfig.com/dashboard-gallery/limits/): The rate limit and daily allowance sitting in front of these endpoints. - [Browse and filter the gallery](https://docs.neuralconfig.com/dashboard-gallery/browsing/): What the facet ids in these responses mean, and how selections combine. - [Troubleshooting](https://docs.neuralconfig.com/dashboard-gallery/troubleshooting/): Every error string these endpoints return, and what each one means. --- # Troubleshooting Source: https://docs.neuralconfig.com/dashboard-gallery/troubleshooting/ Every message below is quoted as the gallery actually returns it. ## The search box ### "Too many questions in a row — give it a minute." You have asked more than **20 questions in a minute** from one address. Wait a minute. Nothing is wrong and nothing is lost. ### "Search has used up today's allowance and is resting until tomorrow — the filters below still work." The day's model allowance is spent. This is not a rate limit and waiting a minute will not clear it — the allowance resets at **00:00 UTC**. Both of these arrive as a `429`, so the sentence is how you tell them apart. The filter rail, the dashboards, the permalinks and every download are unaffected; see [Limits and quotas](https://docs.neuralconfig.com/dashboard-gallery/limits/#what-happens-once-the-allowance-is-spent). ### "Search is unavailable at the moment. Try the filters instead." The model call failed or ran past its **40-second** ceiling. This one is worth retrying — the underlying cause is usually transient. ### "keep it under 800 characters" The question is too long. Questions are capped at 800 characters. ### The answer says nothing matches, but I can see one that does Two things are worth checking before concluding the search is wrong: - **Ask with the words that are on the dashboard**, including the metric. Chart titles and section headings are indexed, so *"err-disabled ports"* finds a dashboard whose own title never says it. - **Name the category.** *"switch related dashboards"* is answered better by naming the Switching tag than by describing it — a dashboard can be about a subject without the word appearing in its text. If it still does not surface, the fastest route is the filter rail: categories are exact where a search is a ranking. ### I asked a follow-up and it did not understand The search takes **one question at a time** and keeps no history — *"and which of those is for switching?"* has nothing to refer back to. Ask the whole question. This is deliberate and is explained in [Ask about the dashboards](https://docs.neuralconfig.com/dashboard-gallery/asking/#every-question-is-a-fresh-one). ## The gallery ### A filter link shows no dashboards Two different causes, and the rail distinguishes them: - **"Some filters in this link no longer exist: `d-sla`."** The link names a category that has since been removed. Click **Remove** to drop just those and keep the rest of the selection. - **"No dashboard carries every category selected."** Every category still exists, but nothing carries all of them at once. Selections are ANDed across kinds, so clearing one widens the results. ### "There is no published dashboard at /d/…" The slug does not name a currently published dashboard. It may never have existed, or it may have been unpublished — an unpublished dashboard serves nothing, including its images and its bundle, even though the files still exist in storage. ### A dashboard image will not load Image URLs carry a **revision number**, and only the revision the record currently points at is served. An older URL — from a cached page, or from editing the number by hand — returns `404`. Reload the gallery to pick up the current one. ## Downloads ### The RUCKUS AI (SmartZone) button is greyed out That platform has no export bundle yet, and the button carries the note *"Coming soon — the converter is being written"*. Constructing the URL by hand does not work around it: the route resolves the platform on the server and answers `404`. See [Download an export bundle](https://docs.neuralconfig.com/dashboard-gallery/downloading/#the-two-platforms). ### "Too many downloads in a row — give it a minute." More than **20 downloads in a minute** from one address. Each download rewrites every identifier in the archive, so this bounds the work rather than your access — wait a minute and the same file is still there. ### The download 404s The dashboard is not currently published, the platform is not available, or the slug does not exist. ### Two people downloaded the same dashboard and got different files **That is correct.** Dashboard and chart identifiers are regenerated on every download, because an import matches objects by identifier and those identifiers match globally across tenants — two identical copies would collide, with the second import overwriting the first person's dashboard. Dataset and database identifiers are the same in every copy, which is what binds the import to a real dataset. ### An imported chart renders empty Check what the chart is filtered on. Filters pinned to tenant-scoped columns — `zoneName`, `ssid`, `apName` and others — are **removed** from the bundle before publishing, so a chart should render against your own data. A chart that comes up empty anyway is usually one whose dataset does not exist in your tenant: bundles reference datasets by identifier and do not contain them. ### The imported dashboard still shows a venue or site name In a chart *title* or a block of text, that is expected and is not a leak of your data — it is a name from the original, which has no shape any pattern can match. These are reviewed by a person before publishing rather than caught by a rule. Values that *do* have a shape are replaced with documentation-range ones: a `192.0.2.x` address or a `host-1.example.com` hostname is a replacement, not a real value. See [What is removed before publishing](https://docs.neuralconfig.com/dashboard-gallery/whats-removed/). ## The request form ### "That verification did not go through. Refresh the page and try again." The bot check failed. A Turnstile token verifies exactly once and lasts five minutes, so the usual causes are a token that was already used or has expired. Refreshing the page is the reliable fix. ### "Say a little more about what you want on it." The description is under **10 characters**. Naming the metric and who it is for is what makes a request buildable. ### "Requests are closed at the moment. Try again later." The bot check is not configured on the server, and the endpoint fails closed rather than accepting unverified submissions. There is nothing you can do from the page; [contact support](https://support.neuralconfig.com/dashboard-gallery?from=docs) if it persists. ### There is no request form anywhere The gallery hides the form entirely when the bot check is not configured, rather than showing one that cannot succeed. ### The "already covered?" cards do not appear They need about **10 characters** to start, and they show nothing at all on any failure — deliberately, since a duplicate check that blocks the form would have inverted its own purpose. The form still sends. ### No clarifying question appeared It needs a draft of about **40 characters**, and it is skipped when the day's model allowance is spent. It is optional in every case — the request sends either way. ## Next steps - [Limits and quotas](https://docs.neuralconfig.com/dashboard-gallery/limits/): Every limit behind the messages on this page, with its exact value. - [Public HTTP API](https://docs.neuralconfig.com/dashboard-gallery/api/): The status code each endpoint returns alongside these messages. - [What is the Dashboard Gallery?](https://docs.neuralconfig.com/dashboard-gallery/): Start here if something on this page did not match what you expected the site to do.