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.

소스 보기

사용 방법

  1. 설치 명령을 복사하고 자신의 에이전트 환경에 설치하기 전에 소스 패키지를 확인하세요.
  2. 필요한 도구, 인증 정보, 지원 환경은 원본 문서에서 확인하세요.
  3. 입력과 원하는 산출물을 설명하고 출처와 결과를 대조하세요.
npx skills add https://github.com/toddlevy/tl-agent-skills --skill tl-docs-viewer-create

시작 전 확인

  • 설치에는 모델 구독, API 한도, 파일 접근 권한이 포함되지 않습니다.
  • 별점 수와 설치 수는 활동 지표이며 독립적인 품질·보안 검증이 아닙니다.
원본 Skill 문서

원본 저장소의 제목, 예시, 코드, 표, 링크, 이미지를 유지해 표시합니다.

<!-- 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

관련 작업

같은 저장소의 Skills

더 많은 Skills

모든 Skills
toddlevy
커뮤니티

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".

설치 수
1
GitHub Stars
0
업데이트
9월 27일
toddlevy
커뮤니티

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.

설치 수
1
GitHub Stars
0
업데이트
9월 27일
toddlevy
커뮤니티

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.

설치 수
1
GitHub Stars
0
업데이트
9월 27일
toddlevy
커뮤니티

tl-openmeter-api

Works with the OpenMeter REST API for usage metering, billing, and entitlements. Covers CloudEvents ingestion, meters, features, plans, customers, subscriptions, entitlements, notifications, billing profiles, invoices, apps, addons, grants, and the Stripe marketplace. Use when integrating OpenMeter, debugging metering, building catalog sync scripts, or when the user mentions OpenMeter API.

설치 수
1
GitHub Stars
0
업데이트
9월 27일