The yufan.me admin console uses a Tiptap (ProseMirror) editor for authoring both posts and pages. Content is stored as PortableText JSON — a structured, portable wire format — and the same PortableText document is used for server-side rendering, RSS feeds, and the OG image generator. Edits round-trip losslessly between the editor and the rendered page.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/syhily/yufan.me/llms.txt
Use this file to discover all available pages before exploring further.
Editor layout
The editor has three interaction layers: Top toolbar — persistent controls across the top of the editor:- Image library picker — insert an image from your S3-backed library
- Music picker — embed a track from the music library
- Link — add or edit a hyperlink on selected text
- Table — insert a table
- Horizontal rule — insert a
<hr>divider - Undo / Redo
- Text selection: Bold, Italic, Strikethrough, Inline code, Link
- Table cell selection: merge cells, add/remove rows and columns, toggle header row
/ on an empty line to open the block insertion menu and choose from the full list of supported block types.
Supported block types
Paragraph
Paragraph
Plain text with inline formatting. Supports bold, italic, strikethrough,
inline code, and hyperlinks via the bubble menu. This is the default block type for all new lines.Headings (H1–H6)
Headings (H1–H6)
Six heading levels available from the slash menu (
/heading) or by typing # through ###### followed by a space. Each heading receives an auto-generated anchor slug derived via the same deriveSlug pipeline used for post slugs — CJK headings are converted to pinyin kebab-case ASCII. The Show ToC toggle on a post or page renders these anchors as a linked table of contents in the sidebar.Blockquote
Blockquote
A styled blockquote block. Insert via
/blockquote or by typing > followed by a space. Supports full inline formatting inside the quote.Code block
Code block
A fenced code block with a language selector. Insert via
/code. Select the programming language from the dropdown that appears on the block — the language tag is stored in the PortableText node and passed to Shiki for syntax highlighting when the page is rendered server-side.Math block
Math block
A display-mode LaTeX math block. Insert via
/math. Write a LaTeX expression directly in the block; the editor shows the raw TeX while authoring. On the rendered page, KaTeX converts the expression to styled math. Inline math is also available via the bubble menu when editing inside a paragraph.Mermaid diagram
Mermaid diagram
A Mermaid DSL code block that renders as an SVG diagram on the public page. Insert via
/mermaid. Write valid Mermaid syntax in the block — for example, graph TD; A-->B;. The editor shows the raw source; the SSR renderer converts it to an SVG at request time.Image
Image
An inline image block with alt text and caption fields. Insert via
/image or the image button in the top toolbar. Images are selected from the image library — you cannot paste an arbitrary URL directly. The image library stores all assets in your S3-compatible bucket. Alt text and caption are edited inline in the React NodeView that wraps the image block.Music player
Music player
Embeds a track from the music library using APlayer. Insert via
/music or the music button in the top toolbar. Tracks are fetched from NetEase Cloud Music via the Meting API and must be added to the music library in Admin → Music before they can be embedded. Lyrics stored in the music.lyric field are available to the player without a second network round trip.Table
Table
A full table with an optional header row. Insert via
/table or the table button in the top toolbar. Use the floating bubble menu when a cell is selected to add or remove rows and columns, merge cells, or toggle the header row. Table cells support inline formatting only — block-level content (headings, code blocks, etc.) is not permitted inside cells.Solution / spoiler
Solution / spoiler
A collapsible block for quiz-style content or hidden hints. Insert via
/solution. The block renders as a closed disclosure widget on the public page; readers click to reveal the content. Useful for tutorials, exercises, or any content that should be opt-in.Footnote
Footnote
A footnote definition linked from an inline footnote reference. Insert via
/footnote. Place the cursor where you want the inline marker and insert a footnote block — the editor links the inline reference number to the definition. On the rendered page, footnote definitions are collected and rendered in a footnotes section at the bottom of the post or page.Saving and publishing
The editor saves content to a draft revision and a published revision independently:- Save draft — writes the current document to the draft revision slot. The public page is not updated.
- Publish — writes the current document to the published revision slot. The public page updates immediately (or at the scheduled publish date if one is set).
Images must be uploaded to the image library before they can be inserted into the editor. The image library requires S3-compatible object storage to be enabled and configured in Admin → Settings → Assets. If S3 is not enabled, the upload button in the library returns a
503 error and no new images can be added. Existing image rows stored before S3 was disabled continue to resolve against the saved publicBaseUrl.