Skip to content
Merged
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
167 changes: 110 additions & 57 deletions dotdog/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -3,67 +3,81 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>dotdog | specdog</title>
<meta name="description" content="dotdog CLI and MCP server for .dog specs, .dag graphs, repo mapping, and multi-repo workspaces.">
<title>dotdog — CLI and MCP tooling | specdog</title>
<meta name="description" content="dotdog CLI and MCP tooling for .dog specs, .dag graphs, repo mapping, and multi-repo workspaces.">
<link rel="llms-txt" href="/llms.txt">
<link rel="icon" type="image/svg+xml" href="/dotdog/assets/dog.svg">
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Organization",
"name": "specdog",
"url": "https://specdog.github.io",
"sameAs": ["https://github.com/specdog", "https://www.npmjs.com/package/dotdog"]
}
</script>
<style>
* { margin: 0; padding: 0; box-sizing: border-box; }
body {
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
background: #ffffff;
color: #1a1a2e;
min-height: 100vh;
padding: 24px;
background: #ffffff; color: #1a1a2e;
min-height: 100vh; padding: 24px;
}
nav {
display: flex;
justify-content: center;
align-items: center;
gap: 18px;
flex-wrap: wrap;
width: min(calc(100vw - 48px), 960px);
margin: 0 auto 32px;
padding: 8px 0 0;
}
nav a { color: #6b7280; text-decoration: none; font-size: .9em; font-weight: 500; line-height: 1.4; }
nav a:hover, nav a.active { color: #d97706; }
main {
max-width: 520px;
margin: 0 auto;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
}
.hero-art { width: 100px; height: 100px; margin-bottom: 8px; }
nav { display: flex; justify-content: center; gap: 18px; padding: 8px 0 32px; flex-wrap: wrap; }
nav a { color: #6b7280; text-decoration: none; font-size: .9em; font-weight: 500; }
nav a:hover { color: #d97706; }
nav a.active { color: #d97706; }
main { max-width: 520px; margin: 0 auto; text-align: center; display: flex; flex-direction: column; align-items: center; }
svg { width: 100px; height: 100px; transition: transform .15s; }
h1 { font-size: 2.4em; font-weight: 700; margin: 12px 0 4px; }
p.tagline { color: #6b7280; font-size: 1.1em; margin-bottom: 4px; line-height: 1.6; }
p.tagline { color: #6b7280; font-size: 1.1em; margin-bottom: 4px; }
p.desc { color: #4b5563; font-size: 0.92em; margin-bottom: 16px; line-height: 1.6; }
.why { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; margin: 16px 0; }
.why span { padding: 4px 10px; border-radius: 12px; font-size: .8em; }
.why span:nth-child(1) { background: #fef3c7; }
.why span:nth-child(2) { background: #dcfce7; }
.why span:nth-child(3) { background: #f3e8ff; }
.why span:nth-child(4) { background: #e7fcef; }
.dog-widget { display: inline-block; cursor: pointer; user-select: none; margin-bottom: 8px; }
#dog-status { font-size: .75em; color: #9ca3af; min-height: 18px; margin: 4px 0; }
.actions { display: flex; gap: 6px; justify-content: center; margin-bottom: 16px; flex-wrap: wrap; }
.actions button { padding: 4px 12px; border-radius: 14px; border: 1px solid #e5e7eb; background: #fff; color: #4b5563; font-size: .78em; cursor: pointer; font-family: inherit; }
.actions button:hover { background: #fef3c7; border-color: #f59e0b; color: #92400e; }
.install-wrap { position: relative; margin-bottom: 20px; width: 100%; }
pre { background: #1e293b; color: #e2e8f0; border-radius: 8px; padding: 16px 20px; text-align: left; font-size: .85em; margin: 0; overflow-x: auto; position: relative; }
pre code { color: #93c5fd; }
code { color: #2563eb; }
.btns { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; margin-bottom: 16px; }
.copy-btn { position: absolute; top: 8px; right: 8px; background: none; border: none; color: #94a3b8; cursor: pointer; padding: 4px 6px; border-radius: 4px; line-height: 1; }
.copy-btn:hover { color: #e2e8f0; background: rgba(255,255,255,0.08); }
.copy-btn.copied { color: #4ade80; }
.copy-btn svg { width: 16px; height: 16px; }
.btns { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; }
a.btn { display: inline-block; padding: 10px 22px; border-radius: 6px; font-size: .92em; font-weight: 600; text-decoration: none; }
a.primary { background: #f59e0b; color: #1a1a2e; }
a.primary:hover { background: #d97706; }
a.secondary { background: #f1f5f9; color: #1e293b; border: 1px solid #cbd5e1; }
a.secondary:hover { background: #e2e8f0; }
.product-grid { display: grid; grid-template-columns: 1fr; gap: 10px; width: 100%; margin: 18px 0 4px; text-align: left; }
.product-card { border: 1px solid #e5e7eb; border-radius: 10px; padding: 12px 14px; background: #fafafa; }
.product-card h2 { color: #1a1a2e; font-size: 1em; margin-bottom: 4px; }
.product-card p { color: #4b5563; font-size: .86em; line-height: 1.45; }
.product-card a { color: #d97706; font-weight: 700; text-decoration: none; }
.line { transition: opacity .15s; }
.cmd { color: #93c5fd; }
.out { color: #86efac; }
.product-grid { display:grid; grid-template-columns:1fr; gap:10px; width:100%; margin:18px 0 4px; text-align:left; }
.product-card { border:1px solid #e5e7eb; border-radius:10px; padding:12px 14px; background:#fafafa; }
.product-card a { color:#d97706; font-weight:700; text-decoration:none; }
.product-card p { margin:4px 0 0; color:#4b5563; font-size:.86em; line-height:1.45; }
footer { margin-top: 24px; color: #9ca3af; font-size: .8em; }
footer a { color: #9ca3af; }


/* shared navigation */
body { padding-top: 24px; margin-top: 0; }
nav {
display: flex;
justify-content: center;
align-items: center;
gap: 18px;
flex-wrap: wrap;
width: min(calc(100vw - 48px), 960px);
margin: 0 auto 32px;
padding: 8px 0 0;
}
nav a { color: #6b7280; text-decoration: none; font-size: .9em; font-weight: 500; line-height: 1.4; }
nav a:hover, nav a.active { color: #d97706; }
/* end shared navigation */
</style>
<link rel="canonical" href="https://specdog.github.io/dotdog">
<link rel="canonical" href="https://specdog.github.io/dotdog/">
</head>
<body>
<nav>
Expand All @@ -78,40 +92,79 @@
<a href="/collar">collar</a>
</nav>
<main>
<img class="hero-art" src="/dotdog/assets/dog.svg" alt="specdog dog logo">
<div class="dog-widget" title="Feed the dog">
<svg id="dog-svg" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 120 120">
<ellipse cx="28" cy="28" rx="13" ry="17" fill="#d97706" transform="rotate(-15 28 28)"/>
<ellipse cx="92" cy="28" rx="13" ry="17" fill="#d97706" transform="rotate(15 92 28)"/>
<circle cx="60" cy="63" r="32" fill="#f59e0b"/>
<circle cx="46" cy="56" r="5" fill="#1a1a2e"/><circle cx="74" cy="56" r="5" fill="#1a1a2e"/>
<circle cx="48" cy="54" r="2" fill="#fff"/><circle cx="76" cy="54" r="2" fill="#fff"/>
<ellipse cx="60" cy="70" rx="7" ry="5" fill="#1a1a2e"/>
<path d="M52 78 Q60 86 68 78" fill="none" stroke="#1a1a2e" stroke-width="2" stroke-linecap="round"/>
<ellipse id="tongue" cx="60" cy="84" rx="5" ry="6" fill="#ef4444" opacity="0" style="transition:opacity .2s"/>
<g id="bone" opacity="0"><path d="M44 80 Q44 70 55 76 L65 76 Q76 70 76 80 Q76 90 65 86 L55 86 Q44 90 44 80 Z" fill="#fef3c7" stroke="#d97706" stroke-width="1.5"/></g>
</svg>
</div>
<div id="dog-status">🐕 Spec</div>
<div class="actions">
<button onclick="feed()">🦴 Feed</button>
<button onclick="pet()">✋ Pet</button>
<button onclick="fetchBall()">🎾 Fetch</button>
</div>

<h1>dotdog</h1>
<p class="tagline">CLI and MCP tooling for structured specs, repo graphs, and multi-repo workspaces.</p>
<p class="desc">dotdog turns `.dog` specs and existing repositories into deterministic `.dag` graphs that agents can query without guessing through the whole codebase.</p>
<p class="tagline">CLI and MCP tooling for specs, graphs, and workspaces.</p>
<p class="desc">dotdog turns .dog specs and existing repositories into deterministic .dag graphs that agents can query without guessing through the whole codebase.</p>

<div class="why">
<span>specs</span>
<span>graphs</span>
<span>MCP</span>
<span>workspaces</span>
<div class="why" style="display:flex;gap:10px;justify-content:center;flex-wrap:wrap;margin:16px 0;">
<span style="background:#fef3c7;padding:4px 10px;border-radius:12px;font-size:.8em;">specs</span>
<span style="background:#dcfce7;padding:4px 10px;border-radius:12px;font-size:.8em;">graphs</span>
<span style="background:#f3e8ff;padding:4px 10px;border-radius:12px;font-size:.8em;">MCP</span>
<span style="background:#e7fcef;padding:4px 10px;border-radius:12px;font-size:.8em;">workspaces</span>
</div>

<div class="install-wrap">
<pre><code>npm install -g dotdog
dotdog workspace init --id example-product
dotdog workspace validate
dotdog workspace graph --json</code></pre>
<button class="copy-btn" onclick="copyInstall(this)" title="Copy">
<svg id="copy-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"/><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/></svg>
</button>
</div>

<div class="btns">
<a class="btn primary" href="https://www.npmjs.com/package/dotdog">Install from npm</a>
<a class="btn secondary" href="https://www.npmjs.com/package/dotdog">npm</a>
<a class="btn secondary" href="https://github.com/specdog/dotdog">GitHub</a>
</div>

<section class="product-grid" aria-label="dotdog capabilities">
<div class="product-card"><h2>Specs</h2><p>Write human-readable `.dog` specs with structured YAML blocks.</p></div>
<div class="product-card"><h2>Graphs</h2><p>Compile deterministic `.dag` graphs for exact agent queries.</p></div>
<div class="product-card"><h2>Repo mapping</h2><p>Map existing code into graph-ready facts instead of starting from a blank spec.</p></div>
<div class="product-card"><h2>Workspace bridge</h2><p>Represent products made from multiple repos with repo-qualified graph facts.</p></div>
<div class="product-card"><h2>MCP tools</h2><p><code>dotdog serve</code> exposes graph queries to MCP-compatible agents.</p></div>
<div class="product-card"><a href="https://github.com/specdog/dotdog">Specs</a><p>Write human-readable `.dog` specs with structured YAML blocks.</p></div>
<div class="product-card"><a href="https://github.com/specdog/dotdog">Graphs</a><p>Compile deterministic `.dag` graphs for exact agent queries.</p></div>
<div class="product-card"><a href="https://github.com/specdog/dotdog">Repo mapping</a><p>Map existing code into graph-ready facts instead of starting from a blank spec.</p></div>
<div class="product-card"><a href="https://github.com/specdog/dotdog">Workspace bridge</a><p>Represent products made from multiple repos with repo-qualified graph facts.</p></div>
</section>

<footer>dotdog · specdog tooling · <a href="https://github.com/specdog/dotdog/blob/main/LICENSE">MIT</a></footer>
<footer>dotdog@<span id="version">0.5.0</span> · <a href="https://github.com/specdog/dotdog/blob/main/LICENSE">MIT</a></footer>
</main>
<script>
const svg=document.getElementById('dog-svg'),st=document.getElementById('dog-status');
const bone=document.getElementById('bone'),tongue=document.getElementById('tongue');
function feed(){bone.setAttribute('opacity','1');st.innerHTML='🦴 Dog fed. Ship with specs!';setTimeout(()=>bone.setAttribute('opacity','0'),1500);}
function pet(){tongue.setAttribute('opacity','1');svg.style.transform='rotate(-5deg)';st.innerHTML='✋ Good dog.';setTimeout(()=>{svg.style.transform='';tongue.setAttribute('opacity','0');},800);}
function fetchBall(){svg.style.transform='translateX(20px)';st.innerHTML='🎾 Fetch!';setTimeout(()=>svg.style.transform='',400);}
svg.parentElement.addEventListener('click',pet);
document.addEventListener('keydown',e=>{if(e.target.tagName==='INPUT'||e.target.tagName==='TEXTAREA')return;if(e.key==='v')feed();if(e.key==='c')fetchBall();if(e.key==='p')pet();});
function copyInstall(btn){
const pre=btn.parentElement.querySelector('pre');
navigator.clipboard.writeText(pre.textContent).then(()=>{
btn.classList.add('copied');
btn.innerHTML='<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"20 6 9 17 4 12\"/></svg>';
setTimeout(()=>{btn.classList.remove('copied');btn.innerHTML='<svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><rect x=\"9\" y=\"9\" width=\"13\" height=\"13\" rx=\"2\" ry=\"2\"/><path d=\"M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1\"/></svg>';},2000);
});
}
async function loadVersion(){try{const r=await fetch('https://registry.npmjs.org/dotdog/latest');const d=await r.json();document.getElementById('version').textContent=d.version;}catch(e){}}
loadVersion();
</script>
</body>
</html>
Loading