agnes-the-ai-analyst/app/web/templates/marketplace_guide.html
Vojtech cb13f80241
feat(marketplace): rename CTA + expand submit-flow guides (#308)
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).
2026-05-14 19:44:33 +02:00

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&nbsp;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>&#x26A1; 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 &rarr;
</a>
</div>
<div class="guide-cta">
<a class="primary" href="/marketplace/guide/flea">Submit a skill to Flea Market &rarr;</a>
<a href="/marketplace?tab=curated">&larr; 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 &rarr;</a>
</div>
{% endif %}
</div>
{% endblock %}