feat(guides): rewrite in-product User Guides as Diátaxis how-tos
All checks were successful
Mirror to GitHub / mirror (push) Successful in 4s
CI / frontend (pull_request) Successful in 4m57s
CI / backend (pull_request) Successful in 10m21s
CI / e2e (pull_request) Successful in 12m0s

Replace 15 feature-dump guides with 43 problem-oriented how-tos grouped
under 10 categories. Drop Maintenance Flows / AI Assistant / Flow Assist
Sparkles — those surfaces no longer exist post-FlowPilot pivot. Rename
Step Library → Solutions Library throughout. Correct every "click X in
the sidebar" reference to match live labels (Home, History, Tickets,
Flows, Scripts, Data, Acct).

Schema: add `category: CategoryId` and optional `relatedSlugs` to Guide;
new Category type and `categories` const drive hub ordering. GuidesHubPage
renders category sections (auto-hides empty); GuideDetailPage renders a
related-guides footer when set; GuideCard drops the misleading "N sections"
subtitle.

Fix step.tip markdown rendering — `**bold**` rendered literally because
tip used plain text instead of the same regex replacement used on
instruction.

14 net-new how-tos for FlowPilot-era surfaces with no prior coverage:
tasklane keyboard flow, view-what-we-know, ask-AI mid-session,
pause-and-leave, resolve, record-fix-outcome, escalate (Escalation
Mode), post-docs-to-ticket, send-client-update, build-script-from-scratch,
open-suggested-flow, pin-a-flow, invite-teammate.

Browser-verified against engineer + owner test users (sidebar labels,
account sub-pages, pilot-screen header buttons, Tasks panel, integration
form). tsc clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-01 21:16:51 -04:00
parent 5e10005276
commit 307a6285e6
9 changed files with 914 additions and 474 deletions

View File

@@ -24,9 +24,6 @@ export function GuideCard({ guide }: GuideCardProps) {
<p className="text-xs text-muted-foreground leading-relaxed">
{guide.summary}
</p>
<span className="mt-2 inline-block font-sans text-[0.625rem] uppercase tracking-widest text-primary">
{guide.sections.length} {guide.sections.length === 1 ? 'section' : 'sections'}
</span>
</div>
</div>
</Link>

View File

@@ -37,7 +37,12 @@ export function GuideSection({ section, index }: GuideSectionProps) {
<div className="mt-2 flex items-start gap-2 rounded-lg bg-primary/5 border-l-2 border-primary px-3 py-2">
<Lightbulb size={14} className="text-primary shrink-0 mt-0.5" />
<p className="text-xs text-muted-foreground leading-relaxed">
<span className="font-semibold text-foreground">Tip:</span> {step.tip}
<span className="font-semibold text-foreground">Tip:</span>{' '}
<span
dangerouslySetInnerHTML={{
__html: step.tip.replace(/\*\*(.*?)\*\*/g, '<strong class="text-foreground font-semibold">$1</strong>'),
}}
/>
</p>
</div>
)}

File diff suppressed because it is too large Load Diff

View File

@@ -47,9 +47,6 @@ export default function GuideDetailPage() {
</div>
</div>
<div className="flex items-center gap-4 mt-4 pt-4 border-t" style={{ borderColor: 'var(--color-border-default)' }}>
<span className="font-sans text-xs text-[0.625rem] uppercase tracking-widest text-muted-foreground">
{guide.sections.length} {guide.sections.length === 1 ? 'section' : 'sections'}
</span>
<span className="font-sans text-xs text-[0.625rem] uppercase tracking-widest text-muted-foreground">
{guide.sections.reduce((acc, s) => acc + s.steps.length, 0)} steps
</span>
@@ -63,6 +60,28 @@ export default function GuideDetailPage() {
))}
</div>
{/* Related guides */}
{guide.relatedSlugs && guide.relatedSlugs.length > 0 && (
<div className="mt-6 card-flat rounded-2xl p-6">
<h2 className="text-sm font-heading font-semibold text-foreground mb-3">Related guides</h2>
<ul className="space-y-2">
{guide.relatedSlugs
.map(slug => guides.find(g => g.slug === slug))
.filter((g): g is NonNullable<typeof g> => Boolean(g))
.map(related => (
<li key={related.slug}>
<Link
to={`/guides/${related.slug}`}
className="text-sm text-primary hover:underline"
>
{related.title}
</Link>
</li>
))}
</ul>
</div>
)}
{/* Back link */}
<div className="mt-6">
<Link

View File

@@ -1,6 +1,6 @@
import { BookOpen } from 'lucide-react'
import { PageMeta } from '@/components/common/PageMeta'
import { guides } from '@/data/guides'
import { categories, guides } from '@/data/guides'
import { GuideCard } from '@/components/guides/GuideCard'
export default function GuidesHubPage() {
@@ -21,11 +21,27 @@ export default function GuidesHubPage() {
</p>
</div>
{/* Guide cards grid */}
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{guides.map(guide => (
<GuideCard key={guide.slug} guide={guide} />
))}
{/* Category sections */}
<div className="space-y-10">
{categories.map(category => {
const categoryGuides = guides.filter(g => g.category === category.id)
if (categoryGuides.length === 0) return null
return (
<section key={category.id}>
<div className="mb-3">
<h2 className="text-base font-heading font-semibold text-foreground">
{category.label}
</h2>
<p className="text-xs text-muted-foreground mt-0.5">{category.description}</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
{categoryGuides.map(guide => (
<GuideCard key={guide.slug} guide={guide} />
))}
</div>
</section>
)
})}
</div>
</div>
</div>