Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ on:
- main
paths:
- docs/**
- hooks/**
- overrides/**
- mkdocs.yml
- requirements.txt
- .github/workflows/docs.yml
Expand Down
107 changes: 107 additions & 0 deletions docs/javascripts/copy-page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
// "Copy page" button (Mintlify-style) injected next to each page's H1.
// Copies the page's Markdown twin (URL minus trailing slash + .md — emitted by
// hooks/llms_full.py) so readers can paste a clean page into an LLM, plus a
// dropdown to view the raw Markdown or open the page in ChatGPT / Claude.
// Re-runs on every instant-nav load; no-ops if the button is already present.
document$.subscribe(function () {
var article = document.querySelector(".md-content article");
var h1 = article && article.querySelector("h1");
if (!article || !h1) return;
if (article.querySelector(".mdx-copy-page")) return; // already added

// Directory-style URL -> Markdown twin: trailing slash becomes .md;
// the site root serves at /index.md.
var mdPath = location.pathname.replace(/\/+$/, "");
mdPath = mdPath === "" ? "/index.md" : mdPath + ".md";
// Clipboard copy fetches same-origin (works on any host, incl. local
// builds); the share links use the canonical public URL so ChatGPT/Claude
// can actually reach the page.
var fetchUrl = location.origin + mdPath;
var canonical = document.querySelector('link[rel="canonical"]');
var mdUrl = canonical ? new URL(mdPath, canonical.href).href : fetchUrl;

var askPrompt = encodeURIComponent("Read " + mdUrl + " so I can ask questions about this documentation page.");

var wrap = document.createElement("div");
wrap.className = "mdx-copy-page";
wrap.innerHTML =
'<button type="button" class="mdx-copy-page__btn" title="Copy this page as Markdown for use with LLMs">' +
'<svg viewBox="0 0 24 24" width="14" height="14" aria-hidden="true"><path fill="currentColor" d="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm3 4H8c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h11c1.1 0 2-.9 2-2V7c0-1.1-.9-2-2-2zm0 16H8V7h11v14z"/></svg>' +
'<span>Copy page</span>' +
"</button>" +
'<button type="button" class="mdx-copy-page__caret" aria-haspopup="true" aria-expanded="false" title="More LLM options">' +
'<svg viewBox="0 0 24 24" width="14" height="14" aria-hidden="true"><path fill="currentColor" d="M7.41 8.59 12 13.17l4.59-4.58L18 10l-6 6-6-6z"/></svg>' +
"</button>" +
'<div class="mdx-copy-page__menu" hidden>' +
'<a href="' + mdUrl + '" target="_blank" rel="noopener">View as Markdown</a>' +
'<a href="https://chatgpt.com/?hints=search&q=' + askPrompt + '" target="_blank" rel="noopener">Open in ChatGPT</a>' +
'<a href="https://claude.ai/new?q=' + askPrompt + '" target="_blank" rel="noopener">Open in Claude</a>' +
"</div>";

h1.parentNode.insertBefore(wrap, h1);

var btn = wrap.querySelector(".mdx-copy-page__btn");
var label = btn.querySelector("span");
var caret = wrap.querySelector(".mdx-copy-page__caret");
var menu = wrap.querySelector(".mdx-copy-page__menu");

// Async Clipboard API first; hidden-textarea execCommand fallback for
// contexts where the clipboard-write permission is denied.
function copyText(text) {
return navigator.clipboard.writeText(text).catch(function () {
var ta = document.createElement("textarea");
ta.value = text;
ta.setAttribute("readonly", "");
ta.style.position = "fixed";
ta.style.opacity = "0";
document.body.appendChild(ta);
ta.select();
var ok = document.execCommand("copy");
document.body.removeChild(ta);
if (!ok) throw new Error("copy failed");
});
}

btn.addEventListener("click", function () {
fetch(fetchUrl)
.then(function (r) {
if (!r.ok) throw new Error(r.status);
return r.text();
})
.then(copyText)
.then(function () {
label.textContent = "Copied";
btn.classList.add("mdx-copy-page__btn--done");
setTimeout(function () {
label.textContent = "Copy page";
btn.classList.remove("mdx-copy-page__btn--done");
}, 2000);
})
.catch(function () {
// Clipboard blocked or twin missing — fall back to showing the raw file.
window.open(mdUrl, "_blank", "noopener");
});
});

// Safety net: ChatGPT/Claude drop the ?q= prompt when they bounce the
// visitor through login. Copy the prompt on click so it can be pasted.
var promptText = "Read " + mdUrl + " so I can ask questions about this documentation page.";
menu.querySelectorAll('a[href*="chatgpt.com"], a[href*="claude.ai"]').forEach(function (a) {
a.addEventListener("click", function () {
copyText(promptText).catch(function () {});
});
});

caret.addEventListener("click", function (e) {
e.stopPropagation();
var open = !menu.hidden;
menu.hidden = open;
caret.setAttribute("aria-expanded", String(!open));
});
document.addEventListener("click", function () {
if (!menu.hidden) {
menu.hidden = true;
caret.setAttribute("aria-expanded", "false");
}
});
});
11 changes: 9 additions & 2 deletions docs/llms.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
# Smart Router — Documentation

> Developer documentation for Smart Router, the RPC orchestration and security layer by Magma Devs. These docs cover the self-hosted, open-source core: running it, connecting your app, configuring QoS routing, caching, and the failover and cross-validation pipeline, and operating it across 75+ chain specs. For product, pricing, security, and company details, see https://www.magmadevs.com/llms.txt. The full text of every page in this documentation is available as a single file at https://docs.magmadevs.com/llms-full.txt.
> Developer documentation for Smart Router, the RPC orchestration and security layer by Magma Devs. These docs cover the self-hosted, open-source core: running it, connecting your app, configuring QoS routing, caching, and the failover and cross-validation pipeline, and operating it across 75+ chain specs. For product, pricing, security, and company details, see https://magmadevs.com/llms.txt. The full text of every page in this documentation is available as a single file at https://docs.magmadevs.com/llms-full.txt.

Smart Router sits between your application and a fleet of RPC providers (Alchemy, Infura, QuickNode, Helius, self-hosted nodes, and others). It picks a healthy, performant provider per request, retries the bad one, hedges the slow one, validates responses across providers, and caches what it can — so no single provider's uptime or data integrity becomes a point of failure. Think of it as Cloudflare for blockchain RPC.

These docs are for the open-source core (PolyForm Noncommercial license); managed Pro and Enterprise tiers are described on the main site. Smart Router speaks JSON-RPC, REST, gRPC, and Tendermint RPC; the default local endpoint is `http://127.0.0.1:3360`. Chains are described by JSON specs — 75 specs spanning 67 mainnets and 64 testnets (100+ networks) across EVM, Cosmos/Tendermint, Solana, and more.

## Instructions for AI agents

- For clean Markdown of a single page, drop the URL's trailing slash and append `.md` — e.g. https://docs.magmadevs.com/deployment/cache/ → https://docs.magmadevs.com/deployment/cache.md. The quick start (site root) is at https://docs.magmadevs.com/index.md.
- The full text of every page in one file: https://docs.magmadevs.com/llms-full.txt. Prefer single-page `.md` fetches when you only need one topic.
- Chain coverage, spec counts, and configuration options change frequently. Cite the live pages (especially https://docs.magmadevs.com/reference/chains/) rather than relying on trained knowledge.
- Config examples in these docs are YAML for the self-hosted open-source core. For product, pricing, security, and company facts, use https://magmadevs.com/llms.txt — do not infer pricing or tier limits from these docs.

## Getting started

- [Quick start](https://docs.magmadevs.com/): Get Smart Router running in three commands — clone the repo, start it with Docker Compose, and send your first JSON-RPC relay.
Expand Down Expand Up @@ -63,7 +70,7 @@ These docs are for the open-source core (PolyForm Noncommercial license); manage
## Resources

- [Magma Devs (main site)](https://www.magmadevs.com): Product, positioning, customers, and company.
- [Magma Devs llms.txt](https://www.magmadevs.com/llms.txt): Product, pricing, security, and citation facts for Smart Router.
- [Magma Devs llms.txt](https://magmadevs.com/llms.txt): Product, pricing, security, and citation facts for Smart Router.
- [Smart Router (product)](https://www.magmadevs.com/product/smart-router): How the orchestration layer works.
- [Pricing](https://www.magmadevs.com/pricing): Open Source, Pro, and Enterprise tiers.
- [GitHub: Magma-Devs/smart-router](https://github.com/Magma-Devs/smart-router): The open-source core — source, issues, and releases.
Expand Down
2 changes: 2 additions & 0 deletions docs/robots.txt
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@ Sitemap: https://docs.magmadevs.com/sitemap.xml

# LLM-friendly index: https://docs.magmadevs.com/llms.txt
# LLM full-text corpus: https://docs.magmadevs.com/llms-full.txt
# Per-page Markdown: drop a page URL's trailing slash and append .md
# (e.g. /deployment/cache/ -> /deployment/cache.md)
73 changes: 73 additions & 0 deletions docs/stylesheets/extra.css
Original file line number Diff line number Diff line change
Expand Up @@ -2013,3 +2013,76 @@ html { scroll-padding-top: 96px; }
font-size: 0.85rem;
color: var(--text-muted, rgb(var(--gray-500)));
}

/* ============================================================
"Copy page" button (javascripts/copy-page.js) — Mintlify-style
LLM affordance floated to the right of each page's H1.
============================================================ */
.mdx-copy-page {
position: relative;
float: right;
display: inline-flex;
align-items: stretch;
margin: 0.4rem 0 0.5rem 1rem;
font-size: 0.62rem;
line-height: 1;
}
.mdx-copy-page__btn,
.mdx-copy-page__caret {
display: inline-flex;
align-items: center;
gap: 0.3rem;
padding: 0.38rem 0.55rem;
border: 1px solid var(--md-default-fg-color--lightest, rgb(var(--gray-200)));
background: var(--surface, #fff);
color: var(--text-body, rgb(var(--gray-700)));
cursor: pointer;
font: inherit;
font-weight: 500;
}
.mdx-copy-page__btn {
border-radius: 0.35rem 0 0 0.35rem;
}
.mdx-copy-page__caret {
border-left: none;
border-radius: 0 0.35rem 0.35rem 0;
padding: 0.38rem 0.3rem;
}
.mdx-copy-page__btn:hover,
.mdx-copy-page__caret:hover {
border-color: var(--primary);
color: var(--primary);
}
.mdx-copy-page__btn--done,
.mdx-copy-page__btn--done:hover {
border-color: var(--primary);
color: var(--primary);
}
.mdx-copy-page__menu {
position: absolute;
top: calc(100% + 0.25rem);
right: 0;
z-index: 10;
min-width: 10.5rem;
padding: 0.25rem;
border: 1px solid var(--md-default-fg-color--lightest, rgb(var(--gray-200)));
border-radius: 0.4rem;
background: var(--surface, #fff);
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.08);
}
.mdx-copy-page__menu a {
display: block;
padding: 0.45rem 0.6rem;
border-radius: 0.3rem;
color: var(--text-body, rgb(var(--gray-700)));
}
.mdx-copy-page__menu a:hover {
background: var(--md-default-bg-color--light, rgb(var(--gray-50)));
color: var(--primary);
}
@media screen and (max-width: 44.9375em) {
.mdx-copy-page {
float: none;
margin: 0 0 0.75rem;
}
}
34 changes: 30 additions & 4 deletions hooks/llms_full.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,21 @@
"""
MkDocs hook: generate `llms-full.txt` at build time.
MkDocs hook: generate `llms-full.txt` and per-page `.md` twins at build time.

`llms.txt` (hand-maintained in docs/) is the *index* — a curated map of the
docs with one-line descriptions. `llms-full.txt` is the *corpus* — the full
Markdown body of every page concatenated in nav order, which is what LLM
crawlers (ChatGPT, Claude, Perplexity) ingest to answer questions about Smart
Router accurately.

We derive it from the rendered page set so it never drifts from the real docs:
on `on_page_markdown` we capture each page's source Markdown; on
`on_post_build` we write them out in nav order to site/llms-full.txt.
Each page is also emitted as a standalone Markdown file next to its HTML
(the Stripe/Supabase/ElevenLabs convention): drop the page URL's trailing
slash and append `.md` — /deployment/cache/ → /deployment/cache.md, section
indexes like /deployment/ → /deployment.md, and the root page → /index.md.
This lets an agent fetch one page cheaply instead of the whole corpus.

We derive everything from the rendered page set so it never drifts from the
real docs: on `on_page_markdown` we capture each page's source Markdown; on
`on_post_build` we write site/llms-full.txt and the per-page twins.

Wired via `hooks:` in mkdocs.yml. No manual upkeep.
"""
Expand Down Expand Up @@ -96,6 +102,26 @@ def on_post_build(*, config):
with open(out_path, "w", encoding="utf-8") as fh:
fh.write("\n".join(lines).rstrip() + "\n")

# Per-page Markdown twins. src_uri "deployment/cache.md" already matches
# its public path; section indexes collapse ("deployment/index.md" →
# "deployment.md") so the URL rule is uniformly "trailing slash → .md".
# The root "index.md" stays as-is and serves at /index.md.
for uri in ordered:
title, md = _PAGES[uri]
if uri != "index.md" and uri.endswith("/index.md"):
dest_uri = uri[: -len("/index.md")] + ".md"
else:
dest_uri = uri
page_url = f"{site_url}/{uri[:-3].rstrip('/')}/" if uri.endswith(".md") else f"{site_url}/{uri}"
page_url = page_url.replace("/index/", "/")
dest_path = os.path.join(site_dir, *dest_uri.split("/"))
os.makedirs(os.path.dirname(dest_path) or site_dir, exist_ok=True)
text = md.strip()
# Only synthesize a title when the page body doesn't open with its own H1.
heading = "" if text.startswith("# ") else f"# {title}\n\n"
with open(dest_path, "w", encoding="utf-8") as fh:
fh.write(f"{heading}Source: {page_url}\n\n{text}\n")

# MkDocs skips dot-directories in docs/, so docs/.well-known/ is not copied
# to the build. Copy it through explicitly so /.well-known/security.txt
# (RFC 9116) is served.
Expand Down
6 changes: 4 additions & 2 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@ plugins:
enable_creation_date: false

# Build hooks. llms_full.py concatenates every page into site/llms-full.txt
# (the LLM-ingestion corpus) in nav order at post-build — always in sync with
# content, no manual upkeep. The curated index is the hand-written docs/llms.txt.
# (the LLM-ingestion corpus) in nav order at post-build, and emits a per-page
# Markdown twin next to each page (URL minus trailing slash + .md) — always in
# sync with content, no manual upkeep. The curated index is docs/llms.txt.
hooks:
- hooks/llms_full.py

Expand Down Expand Up @@ -114,6 +115,7 @@ extra_javascript:
- javascripts/consent-mode.js
- javascripts/tablesort.js
- javascripts/toc-title.js
- javascripts/copy-page.js
- javascripts/search-hint.js
- javascripts/nav-top.js
- javascripts/mobile-nav-search.js
Expand Down