toddlevy/tl-agent-skills

tl-docs-viewer-create

Create a React admin UI for browsing documentation folders with tree navigation, markdown rendering, Mermaid diagrams, and TOC generation.

Ver código fuente
Documento original del Skill

Contenido del repositorio de origen con títulos, ejemplos, código, tablas, enlaces e imágenes preservados.

<!-- Copyright (c) 2026 Todd Levy. Licensed under MIT. SPDX-License-Identifier: MIT -->

Documentation Viewer UI

Create a browseable documentation viewer for admin interfaces with tree navigation, markdown rendering, and Mermaid diagram support.

When to Use

  • "create docs viewer"
  • "add documentation browser"
  • "admin docs UI"
  • "browse docs folder"
  • "docs viewer component"
  • Adding a docs/ browser to an existing admin area
  • Need to view markdown documentation in-app

Outcomes

  • Artifact: React page component with three-column layout (tree + content + TOC)
  • Artifact: Server API endpoints for tree and content
  • Artifact: Supporting components (DocTree, MermaidMarkdown, OnThisPageNav)
  • Decision: Route placement and library choices

Configuration Discovery

Before implementation, gather project context through structured questions. See references/configuration.md for full schemas.

Question Flow

mermaid
flowchart TD
    Start[Trigger skill] --> Scan[Scan for admin patterns]
    Scan --> Q1[Ask: Admin Area]
    Q1 --> Q2[Ask: Frontend Stack]
    Q2 --> Q3[Ask: Route Placement]
    Q3 --> Q4[Ask: Layout Pattern]
    Q4 --> Q5[Ask: Library Preferences]
    Q5 --> Implement[Implement viewer]

Questions Summary

  1. Admin Area Detection — Existing admin area? (yes/no/scan)
  2. Frontend Stack — React Router / Wouter / Next.js / TanStack Router / Remix
  3. Route Placement — Detected path / /admin/docs / /docs / custom
  4. Layout Pattern — Three-column / Two-column / Single column
  5. Library Preferences — Markdown renderer + data fetching choices

Architecture

Three-Column Layout (Default)

┌─────────────────────────────────────────────────────────────┐
│                    Admin Docs Layout                        │
├──────────┬───────────────────────────────────┬──────────────┤
│          │                                   │              │
│  DocTree │         DocContent                │ OnThisPage   │
│  (250px) │         (flex-1)                  │ (200px)      │
│          │                                   │              │
│  ├─ docs │  # Document Title                 │ - Section 1  │
│  │  ├─ a │                                   │ - Section 2  │
│  │  └─ b │  Content rendered from markdown   │   - Sub 2.1  │
│  └─ ...  │                                   │ - Section 3  │
│          │                                   │              │
└──────────┴───────────────────────────────────┴──────────────┘

Data Flow

mermaid
flowchart TD
    subgraph client [Client]
        Page[DocsViewerPage] --> Tree[DocTree]
        Page --> Content[DocContent]
        Page --> TOC[OnThisPageNav]
        Tree -->|select| Router[Router]
        Router -->|path change| Content
    end
    
    subgraph server [Server]
        TreeAPI["GET /admin/docs/tree"]
        ContentAPI["GET /admin/docs/content/*"]
    end
    
    Tree -->|fetch| TreeAPI
    Content -->|fetch| ContentAPI

Phase 1: Server API

Create two endpoints. See references/server-api.md for full patterns.

GET /admin/docs/tree

Returns folder structure as JSON tree.

typescript
interface DocNode {
  name: string;
  path: string;
  type: 'file' | 'folder';
  children?: DocNode[];
}

GET /admin/docs/content/:path*

Returns markdown content and metadata.

typescript
interface DocContent {
  content: string;
  title: string;
  lastUpdated?: string;
  path: string;
}

Phase 2: React Components

Create the component hierarchy. See references/react-components.md for full architecture.

Components

ComponentPurpose
AdminDocsLayoutThree-column layout wrapper
DocTreeRecursive tree navigation
DocTreeItemSingle tree node with expand/collapse
MermaidMarkdownMarkdown renderer with Mermaid support
OnThisPageNavTOC generated from headings

Phase 3: Integration

Route Setup

Based on detected frontend stack:

StackRoute Pattern
React Router<Route path="/admin/docs/*" element={<DocsViewer />} />
Wouter<Route path="/admin/docs/:path*" component={DocsViewer} />
Next.jsapp/admin/docs/[[...path]]/page.tsx
TanStack RoutercreateRoute({ path: '/admin/docs/$path', component: DocsViewer })

Data Fetching

Based on library preference:

LibraryPattern
TanStack QueryuseQuery({ queryKey: ['docs', 'tree'], queryFn: fetchTree })
SWRuseSWR('/admin/docs/tree', fetcher)
Native fetchuseEffect + useState pattern

Dependencies

Configurable via AskQuestion:

CategoryDefaultAlternatives
Markdown@uiw/react-markdown-previewreact-markdown, marked
Data fetching@tanstack/react-queryswr, native fetch
DiagramsmermaidOptional

Verification

After implementation, verify:

  • [ ] Tree loads and displays folder structure
  • [ ] Clicking file loads markdown content
  • [ ] Mermaid diagrams render (if enabled)
  • [ ] TOC generates from headings
  • [ ] Route navigation works
  • [ ] Dark mode supported (if applicable)

References

FilePurpose
references/configuration.mdAskQuestion flows and branching
references/server-api.mdAPI endpoint patterns
references/react-components.mdComponent architecture
references/templates/Code templates


Markdown Rendering

Streamdown (Recommended)

Streaming-optimized React Markdown renderer with built-in Shiki and Mermaid support.

tsx
import { Streamdown } from 'streamdown';
import { code } from '@streamdown/code';
import { mermaid } from '@streamdown/mermaid';

<Streamdown 
  mode="static" 
  plugins={{ code, mermaid }}
  shikiTheme={['github-light', 'github-dark']}
>
  {content}
</Streamdown>

Tailwind v4 Setup — Add to globals.css:

css
@source "../node_modules/streamdown/dist/*.js";
@source "../node_modules/@streamdown/code/dist/*.js";
@source "../node_modules/@streamdown/mermaid/dist/*.js";

Key Props:

PropTypePurpose
mode`"streaming" \"static"`Use static for docs
plugins{ code?, mermaid?, math? }Feature plugins
shikiTheme[light, dark]Code block themes
controlsbooleanCopy buttons

Alternative: react-markdown

If not using Streamdown:

tsx
import ReactMarkdown from 'react-markdown';
import rehypeHighlight from 'rehype-highlight';
import remarkGfm from 'remark-gfm';

<ReactMarkdown
  remarkPlugins={[remarkGfm]}
  rehypePlugins={[rehypeHighlight]}
>
  {content}
</ReactMarkdown>

Search Integration

Pagefind (Static Search)

Best for pre-built docs. Index at build time, search client-side.

tsx
import { search } from '@pagefind/default-ui';

const results = await search(query);

Flexsearch (Client-Side)

Best for dynamic docs loaded at runtime.

tsx
import FlexSearch from 'flexsearch';

const index = new FlexSearch.Index();
docs.forEach((doc, id) => index.add(id, doc.content));
const results = index.search(query);

Search Modal Pattern

tsx
function SearchModal({ isOpen, onClose }) {
  const [query, setQuery] = useState('');
  const results = useSearch(query);

  return (
    <dialog open={isOpen} onClose={onClose}>
      <input 
        value={query} 
        onChange={e => setQuery(e.target.value)}
        placeholder="Search docs..."
        autoFocus
      />
      <ul role="listbox">
        {results.map(r => (
          <li key={r.path} role="option">
            <a href={r.path}>{r.title}</a>
          </li>
        ))}
      </ul>
    </dialog>
  );
}

Keyboard Navigation

Required Shortcuts

KeyAction
/ or Cmd+KOpen search
EscClose search/modal
Navigate results
EnterSelect result
j kNavigate tree (optional)

Implementation

tsx
useEffect(() => {
  const handler = (e: KeyboardEvent) => {
    if (e.key === '/' && !isInputFocused()) {
      e.preventDefault();
      openSearch();
    }
    if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
      e.preventDefault();
      openSearch();
    }
  };
  document.addEventListener('keydown', handler);
  return () => document.removeEventListener('keydown', handler);
}, []);

Accessibility

ARIA Requirements

tsx
<nav aria-label="Documentation navigation">
  <ul role="tree" aria-label="Docs tree">
    <li role="treeitem" aria-expanded={isOpen} aria-selected={isSelected}>
      <button onClick={toggle}>{name}</button>
    </li>
  </ul>
</nav>

<main role="main" aria-label="Documentation content">
  <article>{content}</article>
</main>

<nav aria-label="On this page">
  <ul>{headings.map(h => <li key={h.id}><a href={`#${h.id}`}>{h.text}</a></li>)}</ul>
</nav>

Focus Management

tsx
function DocTree({ items }) {
  const [focusedIndex, setFocusedIndex] = useState(0);
  
  const handleKeyDown = (e: KeyboardEvent) => {
    if (e.key === 'ArrowDown') setFocusedIndex(i => Math.min(i + 1, items.length - 1));
    if (e.key === 'ArrowUp') setFocusedIndex(i => Math.max(i - 1, 0));
    if (e.key === 'Enter') selectItem(items[focusedIndex]);
  };

  return (
    <ul role="tree" onKeyDown={handleKeyDown}>
      {items.map((item, i) => (
        <li 
          key={item.path} 
          role="treeitem"
          tabIndex={i === focusedIndex ? 0 : -1}
          ref={i === focusedIndex ? focusedRef : null}
        >
          {item.name}
        </li>
      ))}
    </ul>
  );
}

MDX Support

For interactive documentation with embedded components:

tsx
import { compile, run } from '@mdx-js/mdx';
import * as runtime from 'react/jsx-runtime';

async function renderMDX(source: string, components: Record<string, Component>) {
  const compiled = await compile(source, { outputFormat: 'function-body' });
  const { default: Content } = await run(compiled, runtime);
  return <Content components={components} />;
}

Custom Components:

tsx
const components = {
  CodePlayground: ({ code }) => <LiveEditor code={code} />,
  Callout: ({ type, children }) => <aside className={`callout-${type}`}>{children}</aside>,
  Steps: ({ children }) => <ol className="steps">{children}</ol>,
};

Documentation Writing Guidelines

From remotion-dev patterns:

  • One API per page — Each function/component gets its own page
  • Don't assume it's easy — Avoid "simply" and "just"
  • Address as "you" — Not "we"
  • Keep it brief — Extra words cause information loss
  • Use headings for fields — Not bullet points for API options
  • Add titles to code fences — Always include file context

Related Skills


References

Quilted Skills

First-Party Documentation

Accessibility

del mismo repositorio

Más Skills

Todos los Skills
toddlevy
Comunidad

tl-agent-plan-execute

Execute a verified plan document. Consumes verification receipts from tl-agent-plan-audit to avoid redundant re-verification. Defines the trust model, staleness protocol, and exit gate execution process. Use when executing a .plan.md file, starting plan implementation, or when the user says "implement the plan" or "execute the plan".

instalaciones
1
GitHub Stars
0
Actualizado
8 sept
toddlevy
Comunidad

tl-kysely-patterns

- Type-safe SQL query building with Kysely for PostgreSQL. Covers query patterns, ExpressionBuilder, JSONB/arrays, migrations, and common pitfalls. Use when writing Kysely queries, creating migrations, debugging type issues, or working with a Kysely codebase.

instalaciones
1
GitHub Stars
0
Actualizado
8 sept
toddlevy
Comunidad

tl-live-music-data

Reference documentation for live music data APIs and ID mapping between services. Use when integrating MusicBrainz, Setlist.fm, JamBase, Bandsintown, Ticketmaster, or other concert/artist APIs.

instalaciones
1
GitHub Stars
0
Actualizado
8 sept
toddlevy
Comunidad

tl-schema-org

The full Schema.org vocabulary -- all 800+ types, 1500+ properties -- with production patterns for JSON-LD rendering, database modeling, API interoperability, extension governance, and rich results. Not just SEO markup. Use when working with structured data, Schema.org types, JSON-LD, or designing data models and APIs grounded in Schema.org.

instalaciones
1
GitHub Stars
0
Actualizado
8 sept