A "Copy prompt for your agent" button in the header copies SKILL.md as a prompt: one line pointing to the hosted file (for agents that can install skills) and then the skill itself, without its frontmatter, so it works in any agent, including one that can't open links. Until SKILL.md loads, or if it can't, the button copies a one-line prompt that points to it. SKILL.md teaches the format, the #d= link recipe in Python and Node, the #md= fallback for agents without code, and how to hand the link over. How it works gets a fourth card, and the README points to both. Two agents given only the copied prompt made working links, one compressed with code and one percent-encoded by hand. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CYHXFvWMCs1GUmRmpySqQ6
519 lines
15 KiB
HTML
519 lines
15 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
<title>.mdeck — plain text in, clean slides out</title>
|
|
<meta name="description" content="Type markdown-ish slides, watch a clean navigable deck render live, copy it as one self-contained HTML file. Free, runs entirely in your browser.">
|
|
<style>
|
|
:root {
|
|
--bg: #0f1115;
|
|
--panel: #171a21;
|
|
--panel-2: #1e222b;
|
|
--ink: #e8eaf0;
|
|
--ink-dim: #9aa1af;
|
|
--accent: #6ea8fe;
|
|
--accent-2: #9d7bff;
|
|
--line: #2a2f3a;
|
|
--radius: 12px;
|
|
}
|
|
* { box-sizing: border-box; }
|
|
html, body { height: 100%; }
|
|
body {
|
|
margin: 0;
|
|
font-family: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
|
|
background: var(--bg);
|
|
color: var(--ink);
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-height: 100vh;
|
|
}
|
|
header {
|
|
padding: 18px 20px 10px;
|
|
display: flex;
|
|
justify-content: space-between;
|
|
align-items: center;
|
|
flex-wrap: wrap;
|
|
gap: 12px;
|
|
}
|
|
header .left {
|
|
display: flex;
|
|
align-items: baseline;
|
|
gap: 12px;
|
|
}
|
|
header h1 {
|
|
margin: 0;
|
|
font-size: 1.35rem;
|
|
letter-spacing: 0.2px;
|
|
}
|
|
header h1 .dot { color: var(--accent); }
|
|
header p {
|
|
margin: 0;
|
|
color: var(--ink-dim);
|
|
font-size: 0.9rem;
|
|
max-width: 62ch;
|
|
}
|
|
header .cta {
|
|
background: linear-gradient(135deg, var(--accent), var(--accent-2));
|
|
color: #0b0d12;
|
|
font-weight: 600;
|
|
border: none;
|
|
border-radius: 9px;
|
|
padding: 8px 16px;
|
|
font-size: 0.85rem;
|
|
text-decoration: none;
|
|
cursor: pointer;
|
|
white-space: nowrap;
|
|
flex-shrink: 0;
|
|
}
|
|
header .cta:hover { filter: brightness(1.08); }
|
|
.early-note {
|
|
margin: 6px 0 0;
|
|
font-size: 0.75rem;
|
|
color: var(--ink-dim);
|
|
grid-column: 1 / -1;
|
|
}
|
|
main {
|
|
flex: 1;
|
|
display: grid;
|
|
grid-template-columns: minmax(280px, 420px) 1fr;
|
|
gap: 14px;
|
|
padding: 12px 20px 16px;
|
|
min-height: 0;
|
|
}
|
|
.editor-pane {
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-height: 0;
|
|
}
|
|
.editor-pane label {
|
|
font-size: 0.78rem;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.08em;
|
|
color: var(--ink-dim);
|
|
margin-bottom: 6px;
|
|
}
|
|
textarea {
|
|
flex: 1;
|
|
min-height: 220px;
|
|
resize: none;
|
|
background: var(--panel);
|
|
color: var(--ink);
|
|
border: 1px solid var(--line);
|
|
border-radius: var(--radius);
|
|
padding: 14px;
|
|
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
font-size: 0.9rem;
|
|
line-height: 1.55;
|
|
outline: none;
|
|
}
|
|
textarea:focus { border-color: var(--accent); }
|
|
.hint {
|
|
margin-top: 8px;
|
|
font-size: 0.78rem;
|
|
color: var(--ink-dim);
|
|
line-height: 1.5;
|
|
}
|
|
.hint code {
|
|
background: var(--panel-2);
|
|
border: 1px solid var(--line);
|
|
border-radius: 5px;
|
|
padding: 1px 5px;
|
|
font-size: 0.75rem;
|
|
}
|
|
.stage {
|
|
display: flex;
|
|
flex-direction: column;
|
|
min-height: 0;
|
|
}
|
|
.toolbar {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: 8px;
|
|
margin-bottom: 10px;
|
|
flex-wrap: wrap;
|
|
}
|
|
button {
|
|
background: var(--panel-2);
|
|
color: var(--ink);
|
|
border: 1px solid var(--line);
|
|
border-radius: 9px;
|
|
padding: 8px 14px;
|
|
font-size: 0.85rem;
|
|
cursor: pointer;
|
|
touch-action: manipulation;
|
|
}
|
|
button:hover { border-color: var(--accent); }
|
|
button:disabled { opacity: 0.4; cursor: default; }
|
|
button.primary {
|
|
background: linear-gradient(135deg, var(--accent), var(--accent-2));
|
|
color: #0b0d12;
|
|
font-weight: 600;
|
|
border: none;
|
|
}
|
|
.counter {
|
|
margin-left: auto;
|
|
font-variant-numeric: tabular-nums;
|
|
color: var(--ink-dim);
|
|
font-size: 0.85rem;
|
|
}
|
|
.progress {
|
|
height: 5px;
|
|
background: var(--panel-2);
|
|
border-radius: 99px;
|
|
overflow: hidden;
|
|
margin-bottom: 10px;
|
|
}
|
|
.progress > div {
|
|
height: 100%;
|
|
width: 0;
|
|
background: linear-gradient(90deg, var(--accent), var(--accent-2));
|
|
transition: width 180ms ease;
|
|
}
|
|
.slide-wrap {
|
|
flex: 1;
|
|
min-height: 0;
|
|
border: 1px solid var(--line);
|
|
border-radius: var(--radius);
|
|
background:
|
|
radial-gradient(1200px 500px at 80% -10%, rgba(110,168,254,0.10), transparent),
|
|
radial-gradient(900px 500px at 0% 110%, rgba(157,123,255,0.10), transparent),
|
|
var(--panel);
|
|
overflow-y: auto;
|
|
touch-action: pan-y;
|
|
}
|
|
.slide {
|
|
--fit: 1;
|
|
padding: clamp(22px, 5vw, 56px);
|
|
min-height: 100%;
|
|
overflow-wrap: anywhere;
|
|
display: flex;
|
|
flex-direction: column;
|
|
justify-content: center;
|
|
}
|
|
.slide h1 {
|
|
font-size: calc(clamp(1.6rem, 4.5vw, 3rem) * var(--fit));
|
|
margin: 0 0 0.5em;
|
|
line-height: 1.15;
|
|
}
|
|
.slide h2 {
|
|
font-size: calc(clamp(1.2rem, 3vw, 1.9rem) * var(--fit));
|
|
margin: 0 0 0.6em;
|
|
color: var(--ink-dim);
|
|
font-weight: 500;
|
|
}
|
|
.slide ul {
|
|
margin: 0;
|
|
padding-left: 1.3em;
|
|
font-size: calc(clamp(1rem, 2.2vw, 1.35rem) * var(--fit));
|
|
line-height: 1.7;
|
|
}
|
|
.slide p {
|
|
font-size: calc(clamp(1rem, 2.2vw, 1.35rem) * var(--fit));
|
|
line-height: 1.7;
|
|
margin: 0.3em 0;
|
|
}
|
|
.slide a {
|
|
color: var(--accent);
|
|
text-decoration: none;
|
|
}
|
|
.slide a:hover {
|
|
text-decoration: underline;
|
|
}
|
|
.slide .empty { color: var(--ink-dim); font-style: italic; }
|
|
.slide code, .export-note code {
|
|
background: rgba(110,168,254,0.12);
|
|
border-radius: 5px;
|
|
padding: 1px 6px;
|
|
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
|
font-size: 0.9em;
|
|
}
|
|
.fit-note {
|
|
font-size: 0.78rem;
|
|
color: var(--ink-dim);
|
|
margin-top: 8px;
|
|
}
|
|
.fit-note.warn { color: #f2c46d; }
|
|
.export-note {
|
|
font-size: 0.78rem;
|
|
color: var(--ink-dim);
|
|
margin-top: 8px;
|
|
}
|
|
section {
|
|
padding: 40px 20px;
|
|
max-width: 1200px;
|
|
margin: 0 auto;
|
|
}
|
|
section h2 {
|
|
margin: 0 0 20px;
|
|
font-size: 1.5rem;
|
|
}
|
|
.steps {
|
|
display: grid;
|
|
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
|
gap: 20px;
|
|
}
|
|
.step {
|
|
background: var(--panel);
|
|
border: 1px solid var(--line);
|
|
border-radius: var(--radius);
|
|
padding: 20px;
|
|
}
|
|
.step h3 {
|
|
margin: 0 0 10px;
|
|
font-size: 1.1rem;
|
|
color: var(--accent);
|
|
}
|
|
.repos {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, 1fr);
|
|
gap: 20px;
|
|
}
|
|
.repo {
|
|
background: var(--panel);
|
|
border: 1px solid var(--line);
|
|
border-radius: var(--radius);
|
|
padding: 20px;
|
|
}
|
|
.repo h3 {
|
|
margin: 0 0 8px;
|
|
font-size: 1.1rem;
|
|
}
|
|
.repo h3 a {
|
|
color: var(--accent);
|
|
text-decoration: none;
|
|
}
|
|
.repo h3 a:hover {
|
|
text-decoration: underline;
|
|
}
|
|
.stars {
|
|
font-size: 0.9rem;
|
|
color: var(--ink-dim);
|
|
margin: 0 0 12px;
|
|
}
|
|
.stars b {
|
|
color: var(--accent);
|
|
}
|
|
.tiers {
|
|
display: grid;
|
|
grid-template-columns: repeat(2, 1fr);
|
|
gap: 30px;
|
|
}
|
|
.tier {
|
|
background: var(--panel);
|
|
border: 1px solid var(--line);
|
|
border-radius: var(--radius);
|
|
padding: 25px;
|
|
}
|
|
.tier h3 {
|
|
margin: 0 0 15px;
|
|
font-size: 1.3rem;
|
|
}
|
|
.tier .price {
|
|
font-size: 1.8rem;
|
|
margin: 0 0 15px;
|
|
}
|
|
.tier ul {
|
|
padding-left: 1.3em;
|
|
margin: 0 0 20px;
|
|
}
|
|
.tier .btn {
|
|
display: inline-block;
|
|
text-decoration: none;
|
|
text-align: center;
|
|
width: 100%;
|
|
}
|
|
.nothing-charged {
|
|
text-align: center;
|
|
font-style: italic;
|
|
color: var(--ink-dim);
|
|
margin: 20px 0 0;
|
|
}
|
|
.limits {
|
|
padding-left: 1.3em;
|
|
color: var(--ink-dim);
|
|
}
|
|
.limits li {
|
|
margin-bottom: 10px;
|
|
}
|
|
footer {
|
|
padding: 20px;
|
|
text-align: center;
|
|
color: var(--ink-dim);
|
|
font-size: 0.9rem;
|
|
border-top: 1px solid var(--line);
|
|
}
|
|
footer a {
|
|
color: var(--accent);
|
|
text-decoration: none;
|
|
}
|
|
footer a:hover {
|
|
text-decoration: underline;
|
|
}
|
|
@media (max-width: 820px) {
|
|
main {
|
|
grid-template-columns: 1fr;
|
|
grid-template-rows: auto 1fr;
|
|
}
|
|
textarea { min-height: 150px; flex: none; }
|
|
.slide-wrap { min-height: 300px; }
|
|
.steps, .repos {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
.tiers {
|
|
grid-template-columns: 1fr;
|
|
}
|
|
header {
|
|
flex-direction: column;
|
|
align-items: flex-start;
|
|
}
|
|
header .left {
|
|
flex-direction: column;
|
|
}
|
|
}
|
|
|
|
/* finish: a one-line header, the product as the whole first screen, and the sections flowing after it (never over it) */
|
|
html, body { height: auto; }
|
|
body { display: block; }
|
|
header { flex-direction: row; align-items: center; gap: 6px 14px; padding: 12px 20px; border-bottom: 1px solid var(--line); }
|
|
header h1 { font-size: 1.4rem; letter-spacing: -0.01em; }
|
|
header .promise { margin: 0; color: var(--ink-dim); font-size: 0.9rem; }
|
|
header .early-note { margin: 0 0 0 auto; font-size: 0.75rem; color: var(--ink-dim); }
|
|
header .agent { padding: 6px 12px; font-size: 0.8rem; white-space: nowrap; }
|
|
main { flex: none; height: calc(100svh - 60px); min-height: 460px; }
|
|
main section { padding: 0; max-width: none; margin: 0; }
|
|
.hint code { white-space: nowrap; }
|
|
@media (max-width: 820px) {
|
|
header { padding: 10px 16px; }
|
|
header .early-note { margin: 0; flex: 1 1 150px; }
|
|
header .agent { order: 1; }
|
|
main { height: auto; min-height: 0; grid-template-rows: auto auto; padding: 12px 16px 16px; }
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<header>
|
|
<h1><span class="dot">.</span>mdeck</h1>
|
|
<p class="promise">Plain text in, slides out.</p>
|
|
<button id="agent" class="agent">Copy prompt for your agent</button>
|
|
<p class="early-note">Opens a public GitHub issue. No email, no payment.</p>
|
|
<a class="cta" href="https://teahub.xyz/teahubxyz/time/issues/new?template=early-access.yml&title=Early+access%3A+.mdeck&venture=mdecks&plan=Pro" target="_blank" rel="noopener">Get early access</a>
|
|
</header>
|
|
<main id="try">
|
|
<section class="editor-pane">
|
|
<label for="src">Slides</label>
|
|
<textarea id="src" spellcheck="false"></textarea>
|
|
<p class="hint">
|
|
<code># Title</code> heading · <code>## Subtitle</code> · <code>- bullet</code> point ·
|
|
<code>---</code> on its own line starts a new slide · inline <code>**bold**</code>, <code>*italic*</code>, <code>`code`</code>.
|
|
Plain lines become paragraphs.
|
|
</p>
|
|
</section>
|
|
<section class="stage">
|
|
<div class="toolbar">
|
|
<button id="prev" aria-label="Previous slide">← Prev</button>
|
|
<button id="next" aria-label="Next slide">Next →</button>
|
|
<button id="copy" class="primary">Copy deck as HTML</button>
|
|
<button id="link">Copy link</button>
|
|
<span class="counter" id="counter">1 / 1</span>
|
|
</div>
|
|
<div class="progress" role="progressbar" aria-label="Deck progress"><div id="bar"></div></div>
|
|
<div class="slide-wrap" id="wrap"><article class="slide" id="slide"></article></div><p class="fit-note" id="fitnote" role="status" hidden></p><p class="fit-note" id="linknote" role="status" hidden></p>
|
|
<p class="export-note">The copied file is a self-contained deck: open it in any browser and use ← / → to present. A copied link carries the deck inside it, after the #, so it opens here with nothing stored.</p>
|
|
</section>
|
|
</main>
|
|
|
|
<section id="how">
|
|
<h2>How it works</h2>
|
|
<div class="steps">
|
|
<div class="step">
|
|
<h3>Type your slides</h3>
|
|
<p>Markdown-ish text in the editor: headings, bullets, paragraphs, <code>---</code> between slides. The syntax is the stuff you already type.</p>
|
|
</div>
|
|
<div class="step">
|
|
<h3>Watch it set live</h3>
|
|
<p>Every keystroke re-typesets the deck on the right. Navigate with arrow keys or swipe; the progress bar keeps your place.</p>
|
|
</div>
|
|
<div class="step">
|
|
<h3>Take the file with you</h3>
|
|
<p>One button copies the deck as a single self-contained HTML file. Open it anywhere, present it offline, email it, done. Or copy a link with the whole deck inside it.</p>
|
|
</div>
|
|
<div class="step">
|
|
<h3>Or ask your agent</h3>
|
|
<p>Press <b>Copy prompt for your agent</b> at the top, paste it into Claude, ChatGPT, Cursor or any other agent, and ask for a deck. It answers with a link that opens here.</p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="why">
|
|
<h2>Why this exists</h2>
|
|
<div class="repos">
|
|
<div class="repo">
|
|
<h3><a href="https://github.com/storytold/wordcraft" target="_blank" rel="noopener">storytold/wordcraft</a></h3>
|
|
<div class="stars">★ <b>5,496</b> stars</div>
|
|
<p>Proof that people want prose in, polished output out — no canvas-dragging required.</p>
|
|
</div>
|
|
<div class="repo">
|
|
<h3><a href="https://github.com/storytold/gridcraft" target="_blank" rel="noopener">storytold/gridcraft</a></h3>
|
|
<div class="stars">★ <b>2,749</b> stars</div>
|
|
<p>Structured text becoming layout: the same bet .mdeck makes for slides.</p>
|
|
</div>
|
|
<div class="repo">
|
|
<h3><a href="https://github.com/storytold/cadcraft" target="_blank" rel="noopener">storytold/cadcraft</a></h3>
|
|
<div class="stars">★ <b>2,552</b> stars</div>
|
|
<p>Even geometry is going plain-text. Your weekly status deck can too.</p>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section id="pricing">
|
|
<h2>Pricing</h2>
|
|
<div class="tiers">
|
|
<div class="tier">
|
|
<h3>Free</h3>
|
|
<div class="price">$0</div>
|
|
<p>For anyone who needs a quick deck right now.</p>
|
|
<ul>
|
|
<li>Full plain-text editor</li>
|
|
<li>Live navigable preview with arrow keys and progress bar</li>
|
|
<li>One-click copy of the deck as self-contained HTML</li>
|
|
<li>Links with the deck inside them, nothing stored</li>
|
|
<li>Runs entirely in the browser; nothing is saved or sent.</li>
|
|
</ul>
|
|
<a class="cta btn" href="#try">Use it free</a>
|
|
</div>
|
|
<div class="tier">
|
|
<h3>Pro</h3>
|
|
<div class="price">$5/mo founding price</div>
|
|
<p>For people who make a deck every week and want it saved and polished.</p>
|
|
<ul>
|
|
<li>Saved decks, themes, speaker notes</li>
|
|
<li>PDF export</li>
|
|
<li>Plain text in, always.</li>
|
|
</ul>
|
|
<a class="cta btn" href="https://teahub.xyz/teahubxyz/time/issues/new?template=early-access.yml&title=Early+access%3A+.mdeck&venture=mdecks&plan=Pro" target="_blank" rel="noopener">Join early access</a>
|
|
</div>
|
|
</div>
|
|
<p class="nothing-charged">Nothing is charged today.</p>
|
|
</section>
|
|
|
|
<section id="limits">
|
|
<h2>Honest limits</h2>
|
|
<ul class="limits">
|
|
<li>Nothing is stored — close the tab without copying a link or the HTML and your text is gone.</li>
|
|
<li>Anyone with a link can read the deck in it, and a very long deck makes a link some apps cut short.</li>
|
|
<li>One layout and one typeface; no themes or branding.</li>
|
|
<li>No images, tables, or nested lists yet.</li>
|
|
<li>No speaker notes, presenter view, or PDF export (that is the Pro idea, if enough people ask for it).</li>
|
|
<li>The copy button needs a modern browser with clipboard access.</li>
|
|
</ul>
|
|
</section>
|
|
|
|
<footer>
|
|
<p>Built by <a href="https://teahub.xyz/teahubxyz/time" target="_blank" rel="noopener">Time, an agent-run venture studio on GitHub</a></p>
|
|
<p><a href="https://teahub.xyz/teahubxyz/time/issues/13" target="_blank" rel="noopener">Want the next version? 👍 the signal issue</a></p>
|
|
</footer>
|
|
|
|
<script src="app.js"></script>
|
|
</body>
|
|
</html> |