Three coordinated tweaks to the publication discovery surface: 1. Action-row CTA on /marketplace?tab=curated reads 'Submit a skill or plugin' instead of 'Submit a plugin'. Skills are first-class citizens of the curated shelf; the old wording made them feel like an afterthought. Same rename in the empty-state JS innerHTML so the two paths can't drift. 2. Curated guide page (/marketplace/guide/curated) expanded from a 4-line stub into a 3-step ordered list documenting the Named Curator handoff (find curator → handoff → publish + lifecycle). New '.guide-fastpath' callout block points users at the Flea Market when they want lighter review-bar / faster path. Primary CTA at the bottom of the curated guide now links to the flea guide too, so users who skim past the fast-path callout still see the escape hatch. 3. Flea guide page (/marketplace/guide/flea) expanded from a 3-line stub into a 4-step ordered list (package → upload via form → automated review → published). Documents the actual /store/new flow + the automated guardrails (manifest, content quality, prompt-injection scan) so users know what 'self-service' actually means before they upload. Route titles updated to match: 'Submit a skill or plugin to Curated Marketplace'. New file: tests/test_web_marketplace_guide.py — three tests covering the CTA rename, the curated guide's structural elements (Named Curators lede, 3 steps, fastpath callout, primary-CTA href), and the flea guide's structural elements (4 steps, no fastpath asymmetry, /store/new primary CTA).
276 lines
11 KiB
HTML
276 lines
11 KiB
HTML
{% extends "base.html" %}
|
|
{% block title %}{{ guide_title }} — {{ config.INSTANCE_NAME }}{% endblock %}
|
|
|
|
{% block content %}
|
|
{# Publication-flow guide. Reached from the action-row CTA on /marketplace
|
|
("Submit a plugin" on the curated tab; the flea variant is reachable
|
|
only as a fallback since flea has a self-service +Upload button).
|
|
|
|
Two distinct flows, one template — `guide_kind` switches the body. #}
|
|
<style>
|
|
.guide-page {
|
|
max-width: 760px; margin: 0 auto;
|
|
padding: 16px 24px 64px;
|
|
color: var(--text-primary);
|
|
}
|
|
.guide-page .back {
|
|
display: inline-flex; align-items: center; gap: 6px;
|
|
margin-bottom: 12px;
|
|
color: var(--text-secondary); font-size: 13px;
|
|
text-decoration: none;
|
|
}
|
|
.guide-page .back:hover { color: var(--primary); }
|
|
|
|
.guide-page h1 {
|
|
font-size: 26px; font-weight: 700;
|
|
margin: 0 0 8px;
|
|
letter-spacing: -0.3px;
|
|
}
|
|
.guide-page .lede {
|
|
font-size: 15px; color: var(--text-secondary);
|
|
line-height: 1.6; margin: 0 0 28px;
|
|
}
|
|
|
|
/* ── Steps ──────────────────────────────────────────────────────── */
|
|
.guide-steps {
|
|
list-style: none; padding: 0; margin: 0 0 32px;
|
|
counter-reset: step;
|
|
}
|
|
.guide-steps li {
|
|
position: relative;
|
|
padding: 14px 18px 14px 56px;
|
|
margin-bottom: 10px;
|
|
background: var(--card-bg);
|
|
border: 1px solid var(--border);
|
|
border-radius: 12px;
|
|
box-shadow: 0 1px 2px rgba(0,0,0,0.04);
|
|
counter-increment: step;
|
|
line-height: 1.55;
|
|
font-size: 14px;
|
|
}
|
|
.guide-steps li::before {
|
|
content: counter(step);
|
|
position: absolute; left: 16px; top: 14px;
|
|
width: 28px; height: 28px;
|
|
display: flex; align-items: center; justify-content: center;
|
|
background: var(--primary); color: #fff;
|
|
border-radius: 999px;
|
|
font-size: 13px; font-weight: 700;
|
|
}
|
|
.guide-steps li strong { color: var(--text-primary); font-weight: 600; }
|
|
.guide-steps li code {
|
|
font-family: var(--font-mono); font-size: 12px;
|
|
background: rgba(0,0,0,0.05); padding: 1px 5px;
|
|
border-radius: 3px; color: var(--text-primary);
|
|
}
|
|
.guide-steps li .note {
|
|
display: block; margin-top: 4px;
|
|
font-size: 12.5px; color: var(--text-secondary);
|
|
}
|
|
|
|
/* Flea variant uses purple step bubbles (matches flea badge accent). */
|
|
.guide-page[data-kind="flea"] .guide-steps li::before { background: #6D28D9; }
|
|
|
|
/* Fast-path callout — visually distinct from the numbered steps so
|
|
readers spot "wait, there's a quicker option" without re-reading
|
|
the whole page. Lives only on the curated guide; flea has no
|
|
equivalent escape hatch (it's already the fast path). */
|
|
.guide-fastpath {
|
|
margin: 16px 0 28px;
|
|
padding: 18px 22px;
|
|
background: linear-gradient(135deg, rgba(109, 40, 217, 0.06), rgba(109, 40, 217, 0.02));
|
|
border: 1px solid rgba(109, 40, 217, 0.25);
|
|
border-left: 4px solid #6D28D9;
|
|
border-radius: 12px;
|
|
}
|
|
.guide-fastpath h3 {
|
|
margin: 0 0 8px;
|
|
font-size: 15px; font-weight: 700;
|
|
color: var(--text-primary);
|
|
}
|
|
.guide-fastpath p {
|
|
margin: 0 0 12px;
|
|
font-size: 14px; line-height: 1.6;
|
|
color: var(--text-secondary);
|
|
}
|
|
.guide-fastpath p strong { color: var(--text-primary); }
|
|
.guide-fastpath a.fastpath-cta {
|
|
display: inline-flex; align-items: center; gap: 6px;
|
|
padding: 8px 14px;
|
|
background: #6D28D9; color: #fff;
|
|
border-radius: 8px;
|
|
font-size: 13px; font-weight: 500;
|
|
text-decoration: none;
|
|
}
|
|
.guide-fastpath a.fastpath-cta:hover { background: #5B21B6; }
|
|
|
|
/* ── Section block ──────────────────────────────────────────────── */
|
|
.guide-section {
|
|
background: var(--card-bg);
|
|
border: 1px solid var(--border);
|
|
border-radius: 12px;
|
|
padding: 22px 26px;
|
|
margin-bottom: 18px;
|
|
box-shadow: 0 1px 2px rgba(0,0,0,0.04);
|
|
}
|
|
.guide-section h2 {
|
|
font-size: 16px; font-weight: 700;
|
|
margin: 0 0 12px;
|
|
}
|
|
.guide-section p {
|
|
margin: 0 0 10px; font-size: 14px; line-height: 1.6;
|
|
color: var(--text-secondary);
|
|
}
|
|
.guide-section p:last-child { margin-bottom: 0; }
|
|
.guide-section p strong { color: var(--text-primary); font-weight: 600; }
|
|
.guide-section code {
|
|
font-family: var(--font-mono); font-size: 12px;
|
|
background: rgba(0,0,0,0.05); padding: 1px 5px;
|
|
border-radius: 3px; color: var(--text-primary);
|
|
}
|
|
|
|
/* ── CTA bar ────────────────────────────────────────────────────── */
|
|
.guide-cta {
|
|
display: flex; gap: 10px; flex-wrap: wrap;
|
|
margin-top: 24px;
|
|
}
|
|
.guide-cta a {
|
|
display: inline-flex; align-items: center; gap: 6px;
|
|
padding: 9px 16px;
|
|
border: 1px solid var(--border);
|
|
background: var(--card-bg);
|
|
color: var(--text-primary);
|
|
border-radius: 8px;
|
|
font-size: 13px; font-weight: 500;
|
|
text-decoration: none;
|
|
transition: all 0.15s ease;
|
|
}
|
|
.guide-cta a:hover { border-color: var(--primary); color: var(--primary); }
|
|
.guide-cta a.primary {
|
|
background: var(--primary); color: #fff; border-color: var(--primary);
|
|
}
|
|
.guide-cta a.primary:hover { background: var(--primary-dark, #0056A3); color: #fff; }
|
|
.guide-page[data-kind="flea"] .guide-cta a.primary {
|
|
background: #6D28D9; border-color: #6D28D9;
|
|
}
|
|
.guide-page[data-kind="flea"] .guide-cta a.primary:hover {
|
|
background: #5B21B6; border-color: #5B21B6;
|
|
}
|
|
</style>
|
|
|
|
<div class="guide-page" data-kind="{{ guide_kind }}">
|
|
<a class="back" href="/marketplace?tab={{ guide_kind }}">← Back to {{ 'Curated Marketplace' if guide_kind == 'curated' else 'Flea Market' }}</a>
|
|
<h1>{{ guide_title }}</h1>
|
|
|
|
{% if guide_kind == 'curated' %}
|
|
{# Curated submission guide — publish-by-curator flow. Named Curators
|
|
are the gatekeepers (security / telemetry hygiene / docs bar). The
|
|
fast-path callout points users at the Flea Market when they want
|
|
reach without the review wait. #}
|
|
<p class="lede">
|
|
Curated Marketplace submissions go through <strong>Named Curators</strong>
|
|
— folks accountable for keeping the bar (security, telemetry hygiene,
|
|
documentation) consistent across what ships on this shelf.
|
|
</p>
|
|
|
|
<ol class="guide-steps">
|
|
<li>
|
|
<strong>Find a Curator.</strong>
|
|
Each plugin in the Curated Marketplace lists its curator on its detail
|
|
page. Reach out to any curator whose published work overlaps with what
|
|
you're shipping — they're the most likely owner. The
|
|
<em>See all curators →</em> link on the
|
|
<a href="/marketplace?tab=curated">Curated tab</a> is the directory entry.
|
|
<span class="note">If no curator's domain matches, ask the
|
|
{{ instance_brand }} platform team — they'll either adopt the
|
|
submission or steer it to the right person.</span>
|
|
</li>
|
|
<li>
|
|
<strong>Hand off your skill or plugin.</strong>
|
|
Share the source repo (or a zipped bundle) plus a one-paragraph intro
|
|
covering <em>what it does</em>, <em>who it's for</em>, and
|
|
<em>what data it touches</em>. The curator runs it through the review
|
|
bar (manifest sanity, prompt-injection surface, doc completeness,
|
|
telemetry posture).
|
|
</li>
|
|
<li>
|
|
<strong>Curator publishes.</strong>
|
|
Once they accept, the curator commits the manifest entry to the
|
|
curated repo. Your plugin appears on the Curated tab on the next
|
|
nightly catalog sync (within ~24 h of merge).
|
|
<span class="note">Iteration after publish goes through the same
|
|
curator — they own the entry's lifecycle (version bumps,
|
|
deprecation, takedown).</span>
|
|
</li>
|
|
</ol>
|
|
|
|
<div class="guide-fastpath">
|
|
<h3>⚡ Want it live in minutes instead of days?</h3>
|
|
<p>
|
|
The <strong>Flea Market</strong> is the self-service shelf — anyone in
|
|
the company can upload a skill, agent, or plugin without going
|
|
through a curator. Same Claude Code reach, faster path, lighter
|
|
review bar (automated guardrails only; no human gatekeeper).
|
|
</p>
|
|
<a class="fastpath-cta" href="/marketplace/guide/flea">
|
|
Submit a skill to Flea Market →
|
|
</a>
|
|
</div>
|
|
|
|
<div class="guide-cta">
|
|
<a class="primary" href="/marketplace/guide/flea">Submit a skill to Flea Market →</a>
|
|
<a href="/marketplace?tab=curated">← Back to Curated</a>
|
|
</div>
|
|
{% else %}
|
|
{# Flea publishing guide — self-service flow. No human gatekeeper,
|
|
automated guardrails only (content quality + security review run
|
|
server-side at submission time). Lives at /store/new. #}
|
|
<p class="lede">
|
|
The Flea Market is self-service. Anyone in the company can upload a
|
|
skill, agent, or plugin — no curator handoff, no review queue.
|
|
Automated guardrails check the manifest, content quality, and
|
|
prompt-injection surface at submission time.
|
|
</p>
|
|
|
|
<ol class="guide-steps">
|
|
<li>
|
|
<strong>Package what you're shipping.</strong>
|
|
A skill is a single <code>SKILL.md</code> (front-matter + body); an
|
|
agent is an <code>AGENT.md</code>; a plugin is a folder with a
|
|
<code>plugin.json</code> manifest and any commands / agents / skills
|
|
it bundles. Zip the folder (or point at a git URL containing it).
|
|
<span class="note">If you're starting fresh, the
|
|
<a href="/marketplace/format-guide">format guide</a> documents each
|
|
shape with copy-pasteable examples.</span>
|
|
</li>
|
|
<li>
|
|
<strong>Upload via the form.</strong>
|
|
Head to <a href="/store/new"><code>/store/new</code></a>. Drop the
|
|
zip (or paste the git URL), fill the metadata form (name, short
|
|
description, what data it touches, who it's for), submit.
|
|
<span class="note">The <em>+ Upload</em> button on the Flea Market
|
|
tab is the same form.</span>
|
|
</li>
|
|
<li>
|
|
<strong>Automated review.</strong>
|
|
Server runs content-quality checks (manifest completeness, prose
|
|
length, distinct-word floor) and a prompt-injection scan. Most
|
|
submissions pass within seconds. Failures surface inline with the
|
|
exact field to fix.
|
|
</li>
|
|
<li>
|
|
<strong>Published.</strong>
|
|
Once green, your submission goes live on the Flea Market tab
|
|
immediately — no nightly-sync delay. Iteration goes through the
|
|
same form: upload a new version, the form recognises the slug
|
|
and bumps the version pointer.
|
|
</li>
|
|
</ol>
|
|
|
|
<div class="guide-cta">
|
|
<a class="primary" href="/store/new">+ Upload to Flea Market</a>
|
|
<a href="/marketplace?tab=curated">Browse Curated →</a>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% endblock %}
|