feat(desktop): embed BoosAPI Desktop client as a subproject

Vendor the rebranded BoosAPI Desktop client (Tauri + Vue) into metapi as
a monorepo subdirectory under desktop/. Source only — node_modules,
dist, Cargo target and the upstream .git history are excluded.

desktop/ keeps its own independent Cargo workspace (desktop/src-tauri
with crates/*); it is not part of the backend boosapi crate, so a
`cargo check` at the metapi root still compiles only the backend. Build
the desktop app from desktop/src-tauri per desktop/README.md.

Note: app icons are still placeholder assets pending the final BoosAPI
logo. The updater signing keys live outside the repo and are not
included.
This commit is contained in:
boos
2026-06-22 11:32:57 +08:00
parent d9c78ecc73
commit e0a5f57793
2305 changed files with 449355 additions and 0 deletions
@@ -0,0 +1,452 @@
# React Quick Start
Get started with markstream-react in your React project.
::: tip Migrating from react-markdown?
If your app already uses `react-markdown`, start with the [migration guide](/guide/react-markdown-migration) and the [migration cookbook](/guide/react-markdown-migration-cookbook) before wiring new code by hand.
:::
## Basic Setup
### 1. Installation
First, install the package:
```bash
pnpm add markstream-react
```
### 2. Import Styles
In your main entry file (e.g., `main.tsx`, `index.tsx`, or `App.tsx`):
```tsx
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import 'markstream-react/index.css'
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<App />
</React.StrictMode>
)
```
### 3. Use the Component
```tsx
import MarkdownRender from 'markstream-react'
function App() {
const markdown = `# Hello React!
This is **markstream-react** - a streaming-friendly Markdown renderer for React.
## Features
- Code syntax highlighting
- Mermaid diagrams
- Math formulas
- And much more!
\`\`\`javascript
console.log('Hello from React!')
\`\`\`
`
return (
<div>
<MarkdownRender content={markdown} />
</div>
)
}
export default App
```
## Using with TypeScript
markstream-react is built with TypeScript and includes full type definitions:
```tsx
import type { NodeRendererProps } from 'markstream-react'
import MarkdownRender from 'markstream-react'
const props: NodeRendererProps = {
content: '# Hello TypeScript!',
}
function App() {
return <MarkdownRender {...props} />
}
```
## Using with Next.js
Use the dedicated SSR entrypoints instead of `mounted` guards or `ssr: false`.
See [React Next SSR](/guide/react-next-ssr) for the full contract and examples.
### App Router (Next.js 14 / 15)
```tsx
import MarkdownRender from 'markstream-react/next'
export default function MarkdownPage() {
const markdown = `# Hello Next.js!
This route ships real SSR HTML first.
`
return <MarkdownRender content={markdown} final />
}
```
### Pages Router
```tsx
import MarkdownRender from 'markstream-react/next'
import 'markstream-react/index.css'
export default function MarkdownPage() {
const markdown = `# Hello Next.js Pages Router!`
return <MarkdownRender content={markdown} final />
}
```
### Pure Server Rendering
```tsx
import MarkdownRender from 'markstream-react/server'
export default function MarkdownPage() {
const markdown = `# Pure server entry`
return <MarkdownRender content={markdown} final />
}
```
## Enabling Optional Features
### Code Syntax Highlighting
Install dependencies:
```bash
pnpm add stream-markdown
```
```tsx
import MarkdownRender, { MarkdownCodeBlockNode, setCustomComponents } from 'markstream-react'
// Use Shiki-based code blocks inside MarkdownRender
setCustomComponents({
code_block: ({ node, isDark, ctx }: any) => (
<MarkdownCodeBlockNode
node={node}
isDark={isDark}
stream={ctx?.codeBlockStream}
{...(ctx?.codeBlockProps || {})}
/>
),
})
function App() {
const markdown = `\`\`\`javascript
const hello = 'world'
console.log(hello)
\`\`\``
return <MarkdownRender content={markdown} />
}
```
### Mermaid Diagrams
Install mermaid:
```bash
pnpm add mermaid
```
Import styles (Mermaid auto-loads when installed):
```tsx
import 'markstream-react/index.css'
function App() {
const markdown = `#### Mermaid Diagram
\`\`\`mermaid
graph TD
A[Start] --> B{Is it working?}
B -->|Yes| C[Great!]
B -->|No| D[Keep trying]
\`\`\``
return <MarkdownRender content={markdown} />
}
```
### D2 Diagrams
Install D2:
```bash
pnpm add @terrastruct/d2
```
```tsx
import 'markstream-react/index.css'
function App() {
const markdown = `#### D2 Diagram
\`\`\`d2
direction: right
Client -> API: request
API -> DB: query
DB -> API: rows
API -> Client: response
\`\`\``
return <MarkdownRender content={markdown} />
}
```
### Math Formulas (KaTeX)
Install katex:
```bash
pnpm add katex
```
Import styles (KaTeX auto-loads when installed):
```tsx
import 'markstream-react/index.css'
import 'katex/dist/katex.min.css'
function App() {
const markdown = `#### Math Example
Inline math: $E = mc^2$
Block math:
$$
\\int_0^\\infty e^{-x^2} dx = \\frac{\\sqrt{\\pi}}{2}
$$`
return <MarkdownRender content={markdown} />
}
```
## Custom Components
You can customize how specific nodes are rendered by passing custom component mappings:
```tsx
import MarkdownRender, { setCustomComponents } from 'markstream-react'
// Custom heading component
function CustomHeading({ node, customId }: any) {
const level = node.level || 1
const Tag = `h${level}` as keyof JSX.IntrinsicElements
return (
<Tag className="custom-heading" data-custom-id={customId}>
{node.children?.map((child: any, i: number) => (
<span key={i}>{child.content || ''}</span>
))}
</Tag>
)
}
// Register for a scoped customId
setCustomComponents('docs', { heading: CustomHeading })
function App() {
const markdown = `# Custom Heading
This heading is rendered with a custom component.
`
return <MarkdownRender customId="docs" content={markdown} />
}
```
## Streaming Content
markstream-react supports streaming markdown content, which is useful for AI-generated content:
```tsx
import MarkdownRender from 'markstream-react'
import { useState } from 'react'
function StreamingDemo() {
const [markdown, setMarkdown] = useState('')
const [isStreaming, setIsStreaming] = useState(false)
const fullText = `# Streaming Demo
This content is being streamed **in small chunks**.
## Features
1. Progressive rendering
2. No layout shift
3. Smooth animations
\`\`\`javascript
const streaming = true
console.log('Streaming enabled:', streaming)
\`\`\`
`
const startStreaming = () => {
setIsStreaming(true)
setMarkdown('')
let i = 0
const interval = setInterval(() => {
if (i < fullText.length) {
setMarkdown(prev => prev + fullText[i])
i++
}
else {
clearInterval(interval)
setIsStreaming(false)
}
}, 20)
return () => clearInterval(interval)
}
return (
<div>
<button onClick={startStreaming} disabled={isStreaming}>
{isStreaming ? 'Streaming...' : 'Start Streaming'}
</button>
<MarkdownRender content={markdown} />
</div>
)
}
```
## Using with React Hooks
```tsx
import type { ChangeEvent } from 'react'
import MarkdownRender from 'markstream-react'
import { useCallback, useEffect, useState } from 'react'
function MarkdownEditor() {
const [content, setContent] = useState('# Edit me!')
const [html, setHtml] = useState('')
const handleChange = useCallback((e: ChangeEvent<HTMLTextAreaElement>) => {
setContent(e.target.value)
}, [])
return (
<div className="markdown-editor">
<textarea
value={content}
onChange={handleChange}
placeholder="Write your markdown here..."
className="editor-input"
/>
<div className="editor-preview">
<MarkdownRender content={content} />
</div>
</div>
)
}
```
## Virtualized Lists
For large markdown documents, you can use virtualization:
```tsx
import MarkdownRender from 'markstream-react'
function LongDocument() {
// Your very long markdown content
const markdown = `# Long Document`
return (
<MarkdownRender
content={markdown}
maxLiveNodes={200}
liveNodeBuffer={10}
/>
)
}
```
## Common Props
Below are the most commonly used props. For the full list, see [React Components](/guide/react-components).
| Prop | Type | Default | Description |
|------|------|---------|-------------|
| `content` | `string` | - | Markdown content to render |
| `nodes` | `BaseNode[]` | - | Pre-parsed AST nodes (typically `ParsedNode[]`) |
| `customId` | `string` | - | Identifier for scoping |
| `maxLiveNodes` | `number` | `320` | Max nodes for virtualization |
| `liveNodeBuffer` | `number` | `60` | Buffer for overscan |
| `batchRendering` | `boolean` | `true` | Enable batched rendering |
| `deferNodesUntilVisible` | `boolean` | `true` | Defer heavy nodes |
| `renderCodeBlocksAsPre` | `boolean` | `false` | Use `<pre><code>` fallback (Mermaid blocks will also fall back) |
## Styling
The default styles are scoped under `.markstream-react` class. You can override styles:
```css
/* Your global styles */
.markstream-react {
font-family: system-ui, -apple-system, sans-serif;
line-height: 1.6;
}
.markstream-react h1 {
font-size: 2.5rem;
font-weight: 700;
border-bottom: 2px solid #e5e7eb;
padding-bottom: 0.5rem;
}
.markstream-react code {
background: #f3f4f6;
padding: 0.2rem 0.4rem;
border-radius: 0.25rem;
}
```
## Using with Tailwind CSS
```tsx
import MarkdownRender from 'markstream-react'
import 'markstream-react/index.css'
import './output.css' // Your Tailwind output
function App() {
return (
<div className="max-w-4xl mx-auto py-8">
<MarkdownRender content="# Hello Tailwind!" />
</div>
)
}
```
## Next Steps
- Explore [React Components documentation](/guide/react-components) for all available components
- Check out [Examples](/guide/examples) for more usage examples
- See [API Reference](/guide/components) for detailed API documentation