The website sources are grouped under WebsiteDev/. site-theseus-x moves there for real (the other site folders are still junctions from WebsiteDev to the root); a junction at the old root path keeps existing scripts working and is ignored so the files are tracked once. Docs, the icon script and the mirror example follow the new path. whitepaper/whitepaper.md is the Markdown the published page was built from, so the text can be edited and rebuilt without the original document.
363 lines
19 KiB
HTML
363 lines
19 KiB
HTML
<!doctype html>
|
||
<html lang="en">
|
||
<head>
|
||
<meta charset="utf-8">
|
||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||
<title>Developers — Theseus.X</title>
|
||
<meta name="description" content="Theseus Navigator developer guide: how the embedded resolver works, how to write a plug-in or an extension, how to add Ariadne's Thread to your own app so your users can resolve BNS names.">
|
||
<link rel="icon" href="assets/favicon.svg" type="image/svg+xml">
|
||
<link rel="mask-icon" href="assets/favicon.svg" color="#d6ff3d">
|
||
<meta property="og:type" content="article">
|
||
<meta property="og:site_name" content="theseus.x">
|
||
<meta property="og:title" content="Developers — Theseus.X">
|
||
<meta property="og:description" content="Resolver spec, plug-in and extension APIs, and how to embed Ariadne's Thread in your own app.">
|
||
<meta property="og:url" content="https://theseus.x/dev/">
|
||
|
||
<style>
|
||
:root{
|
||
--bg:#0b0e14; --panel:#141a24; --panel2:#18202c; --line:rgba(255,255,255,.09);
|
||
--ink:#e7eaf1; --mut:#8b98a9; --dim:#5e6678; --acid:#d6ff3d;
|
||
--ok:#4fd1a5; --warn:#ffc75f;
|
||
}
|
||
*{box-sizing:border-box}
|
||
html{scroll-behavior:smooth}
|
||
body{margin:0;background:radial-gradient(1100px 560px at 50% -12%,#16202e,var(--bg));
|
||
color:var(--ink);font:16px/1.65 system-ui,-apple-system,Segoe UI,Roboto,sans-serif;min-height:100vh;padding-top:52px}
|
||
a{color:var(--acid)}
|
||
.wrap{max-width:900px;margin:0 auto;padding:0 1.2rem}
|
||
|
||
.topnav{position:fixed;top:0;left:0;right:0;z-index:20;display:flex;gap:2px;align-items:center;flex-wrap:wrap;
|
||
padding:10px 1.2rem;background:rgba(11,14,20,.88);backdrop-filter:blur(10px)}
|
||
.topnav .brand{font-weight:600;color:var(--ink);text-decoration:none;margin-right:14px;font-size:15px;
|
||
letter-spacing:.2px;display:flex;align-items:center;gap:8px}
|
||
.topnav .brand .g{color:var(--acid)}
|
||
.topnav .brand svg{width:20px;height:20px}
|
||
.topnav a{color:var(--mut);text-decoration:none;padding:6px 12px;border-radius:8px;font-size:14px;
|
||
display:inline-flex;align-items:center;gap:6px}
|
||
.topnav a:hover{color:var(--ink);background:var(--panel)}
|
||
.topnav a.here{color:var(--acid);background:rgba(214,255,61,.08)}
|
||
.topnav a svg.tabicon{width:15px;height:15px;flex:none}
|
||
.topnav a .g{color:var(--acid)}
|
||
.topnav .menu{display:none}
|
||
@media (max-width:720px){
|
||
.topnav{flex-wrap:nowrap;padding:10px 1rem}
|
||
.topnav .brand{margin-right:0}
|
||
.topnav > a:not(.brand){display:none}
|
||
.topnav .menu{display:block;margin-left:auto;position:relative}
|
||
.topnav .menu > summary{list-style:none;cursor:pointer;padding:8px 10px;
|
||
border-radius:8px;color:var(--mut);display:inline-flex;align-items:center;gap:6px}
|
||
.topnav .menu > summary::-webkit-details-marker{display:none}
|
||
.topnav .menu > summary svg{width:22px;height:22px;display:block}
|
||
.topnav .menu > summary:hover,
|
||
.topnav .menu[open] > summary{color:var(--ink);background:var(--panel)}
|
||
.topnav .menu .menu-panel{position:absolute;top:calc(100% + 6px);right:0;
|
||
background:var(--bg);border:1px solid var(--line);border-radius:12px;
|
||
padding:6px;min-width:220px;display:flex;flex-direction:column;gap:2px;
|
||
box-shadow:0 10px 32px rgba(0,0,0,.55)}
|
||
.topnav .menu .menu-panel a{padding:10px 14px;border-radius:8px;font-size:14.5px;
|
||
color:var(--mut);text-decoration:none;display:flex;align-items:center;gap:8px}
|
||
.topnav .menu .menu-panel a:hover{color:var(--ink);background:var(--panel)}
|
||
}
|
||
|
||
header.hero{text-align:center;padding:4rem 1.2rem 1.5rem}
|
||
.lede-mark{display:inline-block}
|
||
.lede-mark svg{width:72px;height:72px}
|
||
h1{font-size:clamp(1.9rem,5vw,2.6rem);margin:.6rem 0 .4rem;letter-spacing:-.4px}
|
||
h1 .g{color:var(--acid)}
|
||
.tag{color:var(--mut);font-size:1.02rem;max-width:720px;margin:0 auto}
|
||
.tag code{background:#0e131b;border:1px solid var(--line);border-radius:5px;padding:1px 5px;
|
||
font-family:ui-monospace,monospace;font-size:.92em;color:var(--acid)}
|
||
|
||
section{padding:2.2rem 0;border-top:1px solid var(--line);margin-top:2rem;scroll-margin-top:72px}
|
||
section:first-of-type{border-top:none;margin-top:1rem}
|
||
h2{font-size:1.4rem;margin:0 0 .5rem}
|
||
h2 .g{color:var(--acid)}
|
||
h3{font-size:1.05rem;margin:1.3rem 0 .4rem;color:var(--ink)}
|
||
p{color:var(--mut);margin:0 0 .9rem}
|
||
p b{color:var(--ink);font-weight:600}
|
||
ul,ol{color:var(--mut);line-height:1.7;padding-left:1.3rem}
|
||
ul li+li,ol li+li{margin-top:.25rem}
|
||
code{background:#0e131b;border:1px solid var(--line);border-radius:5px;padding:1px 6px;
|
||
font-family:ui-monospace,monospace;font-size:12.5px;color:var(--acid);word-break:break-all}
|
||
pre{background:#0e131b;border:1px solid var(--line);border-radius:10px;padding:14px 16px;overflow-x:auto;
|
||
font-family:ui-monospace,monospace;font-size:12.5px;line-height:1.55;color:#dde3ec;margin:.8rem 0}
|
||
pre code{background:transparent;border:0;padding:0;color:inherit}
|
||
pre .k{color:var(--acid)}
|
||
pre .s{color:#9fd59f}
|
||
pre .c{color:#5e6678;font-style:italic}
|
||
pre .f{color:#8fc5ff}
|
||
|
||
.cards{display:grid;grid-template-columns:repeat(auto-fit,minmax(260px,1fr));gap:14px;margin:1rem 0}
|
||
.card{background:var(--panel);border:1px solid var(--line);border-radius:12px;padding:16px 18px}
|
||
.card h3{margin:0 0 .4rem;font-size:1rem}
|
||
.card p{margin:0;font-size:13.5px}
|
||
.card a.cta{display:inline-block;margin-top:.6rem;color:var(--acid);text-decoration:none;font-size:13px}
|
||
.card a.cta:hover{text-decoration:underline}
|
||
.note{background:var(--panel);border:1px solid var(--line);border-left:3px solid var(--acid);
|
||
border-radius:10px;padding:14px 18px;color:var(--mut);font-size:14px;margin:1.2rem 0}
|
||
.note b{color:var(--ink)}
|
||
|
||
footer.deep{background:linear-gradient(180deg,transparent,rgba(255,255,255,.02));
|
||
border-top:1px solid var(--line);padding:3rem 0 2rem;margin-top:3rem;color:var(--mut);font-size:13.5px}
|
||
footer.deep .fwrap{max-width:980px;margin:0 auto;padding:0 1.2rem;display:grid;
|
||
grid-template-columns:1.5fr repeat(3,1fr);gap:2rem}
|
||
@media (max-width:820px){footer.deep .fwrap{grid-template-columns:1fr 1fr;gap:1.6rem}}
|
||
@media (max-width:460px){footer.deep .fwrap{grid-template-columns:1fr;gap:1.4rem}}
|
||
footer.deep .brand-col{max-width:280px}
|
||
footer.deep .brand-col .brand{display:inline-flex;align-items:center;gap:8px;color:var(--ink);
|
||
text-decoration:none;font-weight:600;font-size:16px;margin-bottom:.5rem}
|
||
footer.deep .brand-col .brand .g{color:var(--acid)}
|
||
footer.deep h5{color:var(--ink);font-size:12px;text-transform:uppercase;letter-spacing:.14em;
|
||
margin:0 0 .8rem;font-weight:600}
|
||
footer.deep ul{list-style:none;padding:0;margin:0;display:flex;flex-direction:column;gap:.5rem}
|
||
footer.deep ul a{color:var(--mut);text-decoration:none;font-size:13.5px}
|
||
footer.deep ul a:hover{color:var(--acid)}
|
||
footer.deep ul a .g{color:var(--acid)}
|
||
footer.deep ul a .ext{color:var(--dim);font-size:11px;margin-left:2px}
|
||
footer.deep .bar{max-width:980px;margin:2rem auto 0;padding:1rem 1.2rem 0;
|
||
border-top:1px solid var(--line);display:flex;justify-content:space-between;gap:1rem;
|
||
flex-wrap:wrap;color:var(--dim);font-size:12px}
|
||
footer.deep .bar .badge{background:rgba(214,255,61,.12);color:var(--acid);
|
||
padding:2px 8px;border-radius:5px;font:600 10px/1.4 system-ui;
|
||
letter-spacing:.14em;text-transform:uppercase;margin-right:8px}
|
||
footer.deep .bar .mono{font-family:ui-monospace,monospace;font-size:11.5px}
|
||
</style>
|
||
</head>
|
||
<body>
|
||
|
||
<nav class="topnav">
|
||
<a class="brand" href="../">
|
||
<svg viewBox="0 0 64 64" aria-hidden="true">
|
||
<rect width="64" height="64" rx="12" fill="#0b0e14"/>
|
||
<path d="M32 6 L38 32 L26 32 Z" fill="#e04e4e"/>
|
||
<path d="M38 32 L32 58 L26 32 Z" fill="#d6ff3d"/>
|
||
<path d="M6 32 L32 27 L58 32 L32 37 Z" fill="#d6ff3d" opacity=".55"/>
|
||
<circle cx="32" cy="32" r="3" fill="#0b0e14"/>
|
||
</svg>
|
||
<span>Theseus<span class="g">.X</span></span>
|
||
</a>
|
||
<a href="../plug-ins/">Plug-ins</a>
|
||
<a href="../extensions/">Extensions</a>
|
||
<a class="here" href="./">Developers</a>
|
||
<a href="//sirius.x/" title="Register a BCNR name"><svg class="tabicon" viewBox="0 0 64 64" aria-hidden="true"><rect width="64" height="64" rx="12" fill="#0b0e14"/><path d="M32 4 L36.4 27.6 L60 32 L36.4 36.4 L32 60 L27.6 36.4 L4 32 L27.6 27.6 Z" fill="#d6ff3d"/></svg><span>Sirius<span class="g">.X</span></span></a>
|
||
<a class="get" href="../#download" style="margin-left:auto;background:rgba(214,255,61,.10);color:var(--acid);font-weight:500">Get Theseus</a>
|
||
<details class="menu">
|
||
<summary aria-label="Open menu">
|
||
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M4 7h16M4 12h16M4 17h16"/></svg>
|
||
</summary>
|
||
<div class="menu-panel">
|
||
<a href="../plug-ins/">Plug-ins</a>
|
||
<a href="../extensions/">Extensions</a>
|
||
<a href="./">Developers</a>
|
||
<a href="//sirius.x/">Sirius.X</a>
|
||
</div>
|
||
</details>
|
||
</nav>
|
||
|
||
<header class="hero">
|
||
<div class="lede-mark">
|
||
<svg viewBox="0 0 64 64" aria-hidden="true">
|
||
<rect width="64" height="64" rx="12" fill="#0b0e14"/>
|
||
<path d="M32 6 L38 32 L26 32 Z" fill="#e04e4e"/>
|
||
<path d="M38 32 L32 58 L26 32 Z" fill="#d6ff3d"/>
|
||
<path d="M6 32 L32 27 L58 32 L32 37 Z" fill="#d6ff3d" opacity=".55"/>
|
||
<circle cx="32" cy="32" r="3" fill="#0b0e14"/>
|
||
</svg>
|
||
</div>
|
||
<h1>Theseus for <span class="g">developers</span></h1>
|
||
<p class="tag">
|
||
Everything you need to extend Theseus Navigator, or borrow its superpower — on-device
|
||
Bitcoin Cash Domain Name resolution — for whatever you are building. Theseus ships
|
||
<a href="../plug-ins/">Ariadne's Thread</a> as a bundled plug-in; the same resolver can live
|
||
inside your app too.
|
||
</p>
|
||
</header>
|
||
|
||
<div class="wrap">
|
||
|
||
<section id="resolver">
|
||
<h2>Resolve BNS names <span class="g">from your own code</span></h2>
|
||
<p>The authoritative developer page is on Ariadne.X — the resolver is the Ariadne project. It
|
||
covers the BNS1 protocol in one page, the record types, a 60-line Node.js resolver you can
|
||
run as-is, and the pointers to every production implementation.</p>
|
||
<div class="cards">
|
||
<div class="card">
|
||
<h3>→ Resolve a BNS name from your own code</h3>
|
||
<p>Protocol, record types, minimum resolver, reference implementations, public endpoints.</p>
|
||
<a class="cta" href="//ariadne.x/dev/">ariadne.x/dev</a>
|
||
</div>
|
||
<div class="card">
|
||
<h3>→ Ariadne's Thread</h3>
|
||
<p>What it is, how it works, system-wide mode, trust model.</p>
|
||
<a class="cta" href="//ariadne.x/thread/">ariadne.x/thread</a>
|
||
</div>
|
||
<div class="card">
|
||
<h3>→ Protocol spec</h3>
|
||
<p>The authoritative BNS1 specification on the forge.</p>
|
||
<a class="cta" href="https://code.silentmode.st/silentmode/ariadne/src/branch/master/Decentralized.DNS/PROTOCOL.md">PROTOCOL.md ↗</a>
|
||
</div>
|
||
</div>
|
||
</section>
|
||
|
||
<section id="embed">
|
||
<h2>Add BNS to <span class="g">your own app</span></h2>
|
||
<p>If you ship any kind of app with a browser surface — Electron, native, game launcher, mail
|
||
client — your users can resolve <code>.bch</code>, <code>.x</code>, <code>.p2p</code> as soon
|
||
as Ariadne's Thread is on the machine. Three paths:</p>
|
||
|
||
<h3>Easiest — chain-install the Windows service</h3>
|
||
<p>Bundle the Thread installer and run <code>AriadneResolver-Setup.exe /S</code> after your own
|
||
install finishes. Theseus does this today. The resolver registers an NRPT rule that only
|
||
affects BNS TLDs, so everything else on the machine is untouched.</p>
|
||
|
||
<h3>JavaScript / Electron — import the resolver</h3>
|
||
<pre><code><span class="k">import</span> { resolveName } <span class="k">from</span>
|
||
<span class="s">"https://code.silentmode.st/silentmode/ariadne/raw/branch/master/Argus/src/lib/resolver-web.js"</span>;
|
||
|
||
<span class="k">const</span> { records } = <span class="k">await</span> <span class="f">resolveName</span>(<span class="s">"sirius.x"</span>);
|
||
<span class="c">// records.s3 → "bns/sirius.x/"</span></code></pre>
|
||
|
||
<h3>Any language — HTTP API against a local Thread</h3>
|
||
<p>If the Thread is installed, it exposes a local HTTP API on <code>127.0.0.1:4626</code>:</p>
|
||
<pre><code>GET /api/name/<name>
|
||
GET /api/dns/<name>
|
||
GET /health</code></pre>
|
||
|
||
<p>Full embedding guide, platform coverage table, and the NSIS/Inno chain-install snippets
|
||
live on <a href="//ariadne.x/dev/#embed">ariadne.x/dev/#embed</a>.</p>
|
||
</section>
|
||
|
||
<section id="extensions">
|
||
<h2>Build an <span class="g">extension</span></h2>
|
||
<p>Extensions are everyone's add-ons: published by any BCNR name holder, signed by that
|
||
name's wallet, verified on your users' devices before a byte runs. They are not plug-ins —
|
||
plug-ins are first-party and ship inside Theseus (see <a href="../plug-ins/">Plug-ins</a>).</p>
|
||
|
||
<h3>Publish an extension</h3>
|
||
<ol>
|
||
<li>Register a <code>.x</code> name on <a href="//sirius.x/">sirius.x</a>.</li>
|
||
<li>Build your extension tarball — same manifest as Chrome extensions plus a Silent Mode
|
||
<code>addon.json</code>.</li>
|
||
<li>Upload it with <code>PUT /api/ext</code>, signed with the wallet that owns the name.</li>
|
||
<li>Theseus verifies the signature against the on-chain owner before installing. Updates work
|
||
the same way; your users' Theseus checks for a newer <code>updates.json</code> on your
|
||
own Sia bucket.</li>
|
||
</ol>
|
||
<p>Walk-through: <a href="../extensions/publish/">theseus.x/extensions/publish</a>.</p>
|
||
</section>
|
||
|
||
<section id="claude">
|
||
<h2>Connect <span class="g">Claude</span> to Theseus</h2>
|
||
<p>The built-in <b>Claude connector</b> is a local MCP server: Claude Code or Claude Desktop on the
|
||
same computer can open and read your tabs, click, type into rich editors, paste formatted text and
|
||
upload files, in the profile where you are already signed in. It is off until you turn it on, and
|
||
it reaches nothing beyond this computer.</p>
|
||
|
||
<h3>Set it up</h3>
|
||
<ol>
|
||
<li>Turn it on in <b>Settings › Extensions › Claude connector</b>. Its panel (the connector icon in
|
||
the toolbar) shows the address, the token, the sites you have approved, the upload folders and a
|
||
live log.</li>
|
||
<li>Copy the command from the panel and run it once. <code>--scope user</code> makes it available in
|
||
every project:</li>
|
||
</ol>
|
||
<pre><code>claude mcp add --scope user --transport http theseus http://127.0.0.1:47800/mcp --header <span class="s">"Authorization: Bearer <token from the panel>"</span></code></pre>
|
||
<p><code>claude mcp list</code> should then show <code>theseus</code> as connected. For <b>Claude Desktop</b>,
|
||
the panel's <i>Claude Desktop</i> tab has a ready <code>claude_desktop_config.json</code> entry. It runs
|
||
a small stdio relay through the Theseus executable itself, so there is nothing else to install.</p>
|
||
|
||
<h3>What Claude can do</h3>
|
||
<p><code>list_tabs</code>, <code>open_tab</code>, <code>navigate</code>, <code>activate_tab</code>,
|
||
<code>close_tab</code>, <code>screenshot</code>, <code>read_page_text</code>, <code>snapshot</code>
|
||
(the accessibility tree, with a ref per element), <code>click</code>, <code>type</code>,
|
||
<code>press_key</code>, <code>paste_html</code>, <code>paste_text</code>, <code>upload_file</code>,
|
||
<code>wait_for</code>, and <code>evaluate</code> while you allow it. Typing is real key input and
|
||
pastes go through the system clipboard and the browser's own paste, so editors such as Medium's
|
||
accept them; your clipboard is put back afterwards.</p>
|
||
|
||
<div class="note"><b>What keeps you in charge.</b> The connector listens on 127.0.0.1 only, behind a
|
||
random token; requests from web pages are refused. There is no browser-wide debugging port: each
|
||
tab is driven on its own. Theseus asks the first time Claude acts on a site. Password and one-time-code
|
||
fields are always refused, files can be uploaded only from folders you add, and running page scripts
|
||
(<code>evaluate</code>) is a separate switch, off by default. Every action is logged with its time.
|
||
The toolbar chip's ✕ stops the connector at once; <i>Revoke token</i> cuts off every client you set
|
||
up.</div>
|
||
<p>Design notes:
|
||
<a href="claude-connector/DESIGN-claude-connector.md">DESIGN-claude-connector.md</a>
|
||
(hosted here ·
|
||
<a href="https://code.silentmode.st/silentmode/theseus/src/branch/master/DESIGN-claude-connector.md">forge mirror ↗</a>).
|
||
The connector shipped with Theseus 0.3.107.</p>
|
||
</section>
|
||
|
||
<section id="plug-ins">
|
||
<h2>Plug-ins <span class="g">(first-party)</span></h2>
|
||
<p>Plug-ins are the few add-ons Silent Mode builds, signs with the operator key, and ships as
|
||
part of Theseus — Aegis wallet, Ariadne's Thread, Shield blocker. Users enable or disable
|
||
them from <b>Settings › Plug-ins</b>.</p>
|
||
<p>If you have an idea for one, open an issue on
|
||
<a href="https://code.silentmode.st/silentmode/theseus">silentmode/theseus</a> first — the
|
||
plug-in surface is intentionally small and we triage proposals before accepting code.</p>
|
||
</section>
|
||
|
||
<section id="source">
|
||
<h2>Where everything lives</h2>
|
||
<ul>
|
||
<li><a href="https://code.silentmode.st/silentmode/theseus">silentmode/theseus</a> — the browser</li>
|
||
<li><a href="https://code.silentmode.st/silentmode/ariadne">silentmode/ariadne</a> — Ariadne.X site + resolver docs</li>
|
||
<li><a href="https://code.silentmode.st/silentmode/sirius">silentmode/sirius</a> — the registrar</li>
|
||
<li><a href="https://code.silentmode.st/silentmode/hephaestus">silentmode/hephaestus</a> — this forge</li>
|
||
</ul>
|
||
</section>
|
||
|
||
</div>
|
||
|
||
<footer class="deep">
|
||
<div class="fwrap">
|
||
<div class="brand-col">
|
||
<a class="brand" href="../">
|
||
<svg viewBox="0 0 64 64" aria-hidden="true" width="24" height="24">
|
||
<rect width="64" height="64" rx="12" fill="#0b0e14"/>
|
||
<path d="M32 6 L38 32 L26 32 Z" fill="#e04e4e"/>
|
||
<path d="M38 32 L32 58 L26 32 Z" fill="#d6ff3d"/>
|
||
<path d="M6 32 L32 27 L58 32 L32 37 Z" fill="#d6ff3d" opacity=".55"/>
|
||
<circle cx="32" cy="32" r="3" fill="#0b0e14"/>
|
||
</svg>
|
||
<span>Theseus<span class="g">.X</span></span>
|
||
</a>
|
||
<p>A Chromium-based browser that resolves Bitcoin Cash Domain Names on the device itself.</p>
|
||
</div>
|
||
<div>
|
||
<h5>Developers</h5>
|
||
<ul>
|
||
<li><a href="./">Theseus dev guide</a></li>
|
||
<li><a href="//ariadne.x/dev/">Resolver guide <span class="ext">↗</span></a></li>
|
||
<li><a href="https://code.silentmode.st/silentmode/theseus">Source <span class="ext">↗</span></a></li>
|
||
</ul>
|
||
</div>
|
||
<div>
|
||
<h5>Product</h5>
|
||
<ul>
|
||
<li><a href="../">Home</a></li>
|
||
<li><a href="../plug-ins/">Plug-ins</a></li>
|
||
<li><a href="../extensions/">Extensions</a></li>
|
||
<li><a href="../brand/">Brand book</a></li>
|
||
<li><a href="../whitepaper/">Whitepaper</a></li>
|
||
</ul>
|
||
</div>
|
||
<div>
|
||
<h5>Pantheon</h5>
|
||
<ul>
|
||
<li><a href="//ariadne.x/">Ariadne<span class="g">.X</span> — mobile</a></li>
|
||
<li><a href="//sirius.x/">Sirius<span class="g">.X</span> — names</a></li>
|
||
<li><a href="//hephaestus.x/">Hephaestus<span class="g">.X</span> — forge</a></li>
|
||
</ul>
|
||
</div>
|
||
</div>
|
||
<div class="bar">
|
||
<span><span class="badge">Alpha</span>theseus.x — a BCNR name resolving to a Sia-hosted site</span>
|
||
<span class="mono">MPL-2.0 · docs CC BY 4.0</span>
|
||
</div>
|
||
</footer>
|
||
|
||
</body>
|
||
</html>
|