Skip to content

Feature idea: embeddable widget mode (URL flags) + a realm interaction map #11

Open

Description

@moul

Two related feature ideas from building Gnomputer (a Gno desktop-in-browser PWA that embeds mygnoscan via iframe). Posting as a proposal, not a request for immediate work — happy to help scope further.

1. Embeddable "widget mode" via URL flags

Right now embedding mygnoscan means iframing the full site (nav, theme, chrome and all). A URL flag (e.g. ?embed=1 or ?widget=graph) that strips the outer chrome and renders just one piece of content — a single graph, a single table, a single stat — would let a host app embed just the useful part instead of a whole page-in-a-page. Concretely useful pieces to expose this way: the per-realm dependency graph (/realm/:path?tab=graph), the gas/analytics leaderboards, a single block or tx detail view.

2. A realm interaction map

A visual "map" of realm activity: circles sized by request volume in a chosen timeframe, grouped by namespace (a big circle per address/org, smaller circles inside it for each realm that namespace owns), with arrows between realms for real dependency edges (sized/weighted by call volume, not just "exists"). A v2 could add arrows radiating in from outside the diagram to represent external callers/users hitting a realm, to visualize real traffic patterns, not just the static dependency graph mygnoscan's /realm/:path graph tab already shows.

This is a bigger, more novel feature than #1 — could live here (mygnoscan already has the indexer data and the existing d3-force graph to build on) or could be built directly in a consumer app; flagging it here first since mygnoscan's backend is the natural home for the aggregation query it'd need (activity-per-realm-per-timeframe, which isn't exposed by any current /api/* endpoint).

Context

Related tracking: moul/gnomputer#69 (a "see the impact of an action live" demo concept this map/embed mode would help support). Also see the existing backend/API feedback meta-issue for smaller, concrete bugs found during the same integration work.

Activity

  1. moul commented on Aug 5, 2026

    @moul
    CollaboratorAuthor

    Some implementation notes from reading the code (audit 2026-08-05), relevant to scoping both parts:

    Part 1 (widget mode) is mostly mechanical but the frontend is a single 3315-line frontend/index.html with markup, CSS and JS inline, so "strip the chrome" means introducing a real render-mode branch rather than toggling a CSS class on an existing component boundary — there are not many boundaries yet. Worth doing after (or alongside) any frontend restructuring; landing it first means doing it twice.

    Part 2 (realm interaction map) — the renderer is in better shape than the data layer:

    • The d3-force graph already exists and is good (index.html:2956). What is coupled to the dependency-graph shape is narrow: node radius (index.html:3088) and depthColor. Feeding it an activity-weighted graph is mostly a new data adapter, not a new renderer.
    • The blocker is the aggregation query, as you guessed. The data contract today is a dependency graph ({path: [imports]}) with no weights.
    • Per-realm timeframe aggregation exists, but only for storage: GetStorageTimeSeries (db.go:1387), exposed as /api/timeseries/storage?realm=. There is no per-realm activity series anywhere.
    • Closest path to what you want: mirror GetStorageTimeSeries with calls as the source plus AND pkg_path = ?, reusing the existing fillBuckets helper, and add an index on (network, pkg_path, block_time).
    • Namespace grouping (big circle per address/org, realms nested inside) can come straight from packages.creator, which is already stored and indexed.
    • For the dependency arrows weighted by call volume rather than mere existence, note that the existing analytics JOINs group calls/dependencies by path without network in the key (db.go:967) — so cross-network double-counting is a live risk for exactly this kind of aggregation. Worth fixing as part of the query work rather than after.

    So: the map is realistically "one new aggregation endpoint + one adapter", with the network-scoping bug as a prerequisite. Filed #20 tracking the structural work; #14 covers tests for the multi-network query cases that this feature would otherwise trip over.

  2. moul commented on Sep 22, 2026

    @moul
    CollaboratorAuthor

    Status check against the deployed instance, 2026-09-22. Part 1 shipped, and most of part 2 shipped under a different name. What is genuinely left is one specific thing, and it is worth stating precisely rather than leaving this open as a whole feature.

    Part 1: embed mode is live

    ?embed=1 works on every route, and the 2026-08-05 audit's worry about it — "the frontend is a single 3315-line index.html, so strip the chrome means introducing a real render-mode branch" — turned out to be answerable with a class instead. An inline script in <head> reads the flag before the body exists and sets html.embed; the rest is CSS.

    curl -s 'https://mygnoscan.moul.p2p.team/realm/r/gov/dao?embed=1'
    

    Header, footer, rail, the section strips and the sanity subbar are hidden, the container loses its padding and the background goes transparent so a host page shows through. e2e/tests/embed.spec.js pins both halves: the chrome is gone and the content is still there (a blank iframe would satisfy the first assertion on its own), and that nothing changes without the flag.

    Part 2: /contracts is the realm interaction map

    Built as its own page rather than as a second mode of the dependency graph, which is why it did not read as an answer to this issue. Against this issue's description, item by item:

    asked for where it is
    circles sized by request volume in a chosen timeframe /api/contracts/map?window= with metric=calls; also importers, gas, unique_callers
    grouped by namespace, a big circle per org with its realms inside namespace on every node; the packed and bundled views nest by it
    arrows for real dependency edges /api/contracts/edges?kind=imports
    weighted by call volume, not just "exists" not done for import edges. kind=callers edges are weighted (shared callers, weight: 393 on wugnot -> gnoswap/router today), but an import edge is still binary
    v2: arrows radiating in from outside for external callers not done

    Five layouts (orbit, packed, bundled, chord, treemap), and the realm page links straight into it centred on itself.

    The 2026-08-05 audit's two prerequisites are both resolved. The network-scoping bug it flagged — analytics JOINs grouping calls/dependencies by path without network in the key — is fixed; singleNetwork makes /api/contracts/* refuse the all-chains case outright rather than blending it. And the per-realm aggregation it said was the blocker exists as /api/realm/usage/{path}, with a window filter, per-caller and per-function breakdowns.

    Two things the map learned that this issue did not anticipate, both of which turn the picture to mud without them: an edge needs two addresses in common (one address touching two contracts once is a coincidence, and at min=1 the map is mostly coincidences), and an address that touched more than 30 contracts is excluded from edge generation, because one bot calling fifty contracts links all of them to each other. Its calls still count toward every node's size.

    What is actually left

    Weighted import edges. An import edge today says the import exists. Sizing it by the calling realm's traffic would say how much of the chain's activity actually flows through a given package, which is the question this issue asked and the one importers (a count of dependents, regardless of whether any of them is used) cannot answer. p/nt/ufmt/v0 has 103 dependents on mainnet and zero calls of its own, and there is currently no way to tell which of those 103 are live.

    External-caller arrows. Genuinely not started. Worth deciding whether it is one node per caller (unreadable past a few dozen) or an aggregated inbound weight per realm drawn on the node itself, which is probably the same picture with none of the mud.

    Leaving this open for those two. Everything else here is shipped.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions