
MDX Syntax Available on nisshi.dev Blog
This page was auto-generated from the source code using Claude Code Agent Skills (Claude Opus 4.6), then reviewed and edited by the author (nisshi-dev).
This blog is built with MDX syntax support. It's based on Fumadocs, a documentation framework, with custom remark plugins and React components added on top, allowing interactive content like 3D models to be embedded directly in articles.
This page introduces the available syntax and components with live previews. If you're looking to achieve something similar in your own MDX blog, I hope this serves as a useful reference.
The UI component catalog (Storybook) is published at the link below if you're interested.
Basic Markdown Syntax
Headings
## Heading 2
### Heading 3
#### Heading 4Text Formatting
**Bold text**
*Italic text*
~~Strikethrough~~
`Inline code`Bold text, Italic text, Strikethrough, Inline code
Lists
- Bullet item 1
- Bullet item 2
- Nested item
1. Numbered item 1
2. Numbered item 2- Bullet item 1
- Bullet item 2
- Nested item
- Numbered item 1
- Numbered item 2
Blockquotes
> This is a blockquote.
> It can span multiple lines.This is a blockquote. It can span multiple lines.
Links
External and internal links are displayed differently. External links automatically get an indicator (↗) showing they lead to an external site.
External Links
[Google](https://google.com)Internal Links
[Blog posts](/blog)Code Blocks
Basic
```js
console.log('Hello World');
```console.log('Hello World');With Filename
You can display a filename using the title option.
```typescript title="src/components/Button.tsx"
export function Button({ onClick }: { onClick: () => void }) {
return <button onClick={onClick}>Click me</button>;
}
```export function Button({ onClick }: { onClick: () => void }) {
return <button onClick={onClick}>Click me</button>;
}Line Numbers
You can display line numbers with the lineNumbers option. You can also specify a starting line number.
```js lineNumbers
function hello() {
console.log("Hello");
}
```
```js lineNumbers=10
// Starting from line 10
function world() {
console.log("World");
}
```function hello() {
console.log("Hello");
}// Starting from line 10
function world() {
console.log("World");
}Line Highlighting
You can highlight specific lines using Shiki transformers.
```js
const highlighted = true;
const normal = true;
```const highlighted = true;
const normal = true;Diff Display
You can visually display added and removed lines.
```js
console.log("Hello");
console.log("World");
```console.log("Hello");
console.log("World"); Syntax Highlighting
def hello_world():
print("Hello, World!")
hello_world()npm install my-package{
"name": "my-project",
"version": "1.0.0"
}Package Install
Displays with tabs for switching between npm/yarn/pnpm/bun.
```package-install
my-package
```npm install fumadocs-uiTypeScript ⇔ JavaScript Toggle
You can toggle between TypeScript and JavaScript with the ts2js option.
```tsx ts2js
import { ReactNode } from 'react';
export default function Layout({ children }: { children: ReactNode }) {
return <div>{children}</div>;
}
```import { ReactNode } from 'react';
export default function Layout({ children }: { children: ReactNode }) {
return <div>{children}</div>;
}Tabbed Code Blocks
You can display multiple code blocks as tabs using the tab option.
```ts tab="TypeScript"
const message: string = "Hello";
```
```js tab="JavaScript"
const message = "Hello";
```const message: string = "Hello";Callouts
You can create callout blocks using the :::type syntax.
| Type | Usage |
|---|---|
info | Supplementary information (default) |
note / tip | Aliases for info |
warning / warn | Warnings and cautions |
danger | Errors and critical warnings |
success | Success and completion messages |
With Custom Title
You can set a custom title using the :::type[title] syntax.
:::info[Additional Info]
This is supplementary information with a custom title.
:::
:::info
This is supplementary information.
:::
:::warning
This is a warning message.
:::
:::danger
This is an error message.
:::
:::success
This is a success message.
:::Additional Info
This is supplementary information with a custom title.
This is supplementary information.
This is a warning message.
This is an error message.
This is a success message.
Cards
Displays links to related pages in a card layout.
<Cards>
<Card title="Learn about Next.js" href="https://nextjs.org/docs" />
<Card title="Learn about Fumadocs" href="https://fumadocs.dev" />
</Cards>With Descriptions
<Cards>
<Card href="https://nextjs.org/docs" title="Data Fetching">
Learn about data fetching methods in Next.js
</Card>
<Card title="href is optional">
You can also create description-only cards without links
</Card>
</Cards>Data Fetching
Learn about data fetching methods in Next.js
href is optional
You can also create description-only cards without links
Link Card (Link Preview)
nisshi.dev Custom Implementation
This component is a custom implementation for nisshi.dev. It automatically fetches OGP information and displays a link card.
When you write a URL on its own line, it automatically becomes an OGP-powered link card.
https://nextjs.org
https://fumadocs.dev
https://github.com/honojs/honoManual Specification
You can also manually specify link card content using the LinkCard component.
| Prop | Type | Required | Description |
|---|---|---|---|
| url | string | ✅ | Link URL |
| title | string | - | Title (skips OGP fetching when specified) |
| description | string | - | Description text |
| image | string | - | Image URL |
<LinkCard
url="https://example.com"
title="Site Title"
description="Site description"
/>Math (KaTeX)
You can write mathematical expressions using LaTeX notation.
Inline
Pythagorean theorem: $$c = \pm\sqrt{a^2 + b^2}$$Pythagorean theorem:
Block
```math
E = mc^2
``````math
\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}
```Media Embedding
Images
nisshi.dev Custom Implementation
Images can be enlarged by clicking. This uses react-medium-image-zoom.

Figure (Image with Caption)
nisshi.dev Custom Implementation
This component is a custom implementation for nisshi.dev.
A component for adding captions to images and other elements.
| Prop | Type | Required | Description |
|---|---|---|---|
| caption | ReactNode | ✅ | Caption (text or JSX) |
| children | ReactNode | ✅ | Child elements (images, etc.) |
| className | string | - | Custom class name |
<Figure caption="Event venue">

</Figure>Video
nisshi.dev Custom Implementation
This component is a custom implementation for nisshi.dev. For WebM format, it automatically adds an MP4 fallback. It uses media-chrome.
A video player component.
| Prop | Type | Required | Description |
|---|---|---|---|
| src | string | ✅ | Video URL |
| fallbackSrc | string | - | Fallback video URL |
| alt | string | - | Alt text (for accessibility) |
| poster | string | - | Poster image URL |
| autoPlay | boolean | - | Auto-play (default: false) |
| loop | boolean | - | Loop playback (default: false) |
| muted | boolean | - | Muted (default: false) |
| children | ReactNode | - | Caption |
<Video src="/content/blog/example/video.webm" alt="Demo video playback">
Video description text
</Video>Displaying a 3D model with Quick Look on iPad OS
Model3D (3D Model)
nisshi.dev Custom Implementation
This component is a custom implementation for nisshi.dev. It uses @google/model-viewer. It supports AR features (iOS Quick Look / Android Scene Viewer).
Displays 3D models in GLB/GLTF format. You can rotate, zoom, and pan using camera controls.
| Prop | Type | Required | Description |
|---|---|---|---|
| src | string | ✅ | Model file path |
| alt | string | - | Model description (for accessibility) |
| children | ReactNode | - | Caption |
| height | string | number | - | Viewer height (default: "400px") |
| autoRotate | boolean | - | Auto-rotate (default: false) |
| autoRotateSpeed | number | - | Auto-rotate speed (degrees/sec, default: 30) |
| ar | boolean | - | Enable AR (default: true) |
| poster | string | - | Poster image URL |
| iosSrc | string | - | USDZ file path for iOS |
<Model3D src="/models/robot.glb" alt="Robot model" autoRotate>
3D robot model (drag to rotate, scroll to zoom)
</Model3D>Spacesuit 3D model (drag to rotate, scroll to zoom)
VrmViewer (VRM Avatar)
nisshi.dev Custom Implementation
This component is a custom implementation for nisshi.dev. It uses @pixiv/three-vrm and React Three Fiber. It supports both VRM 0.x and 1.0, including SpringBone physics.
Displays VRM-format 3D avatars. You can rotate, zoom, and pan using OrbitControls.
| Prop | Type | Required | Description |
|---|---|---|---|
| src | string | ✅ | VRM file path |
| alt | string | - | Model description (for accessibility) |
| children | ReactNode | - | Caption |
| height | string | number | - | Viewer height (default: "350px") |
| autoRotate | boolean | - | Auto-rotate (default: false) |
| autoRotateSpeed | number | - | Auto-rotate speed (default: 1.0) |
| scale | number | - | Model scale (default: 1) |
| cameraPosition | [number, number, number] | - | Initial camera position (default: [0, 1.5, 3]) |
| debug | boolean | - | Show debug info (default: false) |
<VrmViewer src="/models/avatar.vrm" alt="VRM avatar">
VRM avatar (drag to rotate, scroll to zoom)
</VrmViewer>VRM avatar (drag to rotate, scroll to zoom)
SplatViewer (3D Gaussian Splat)
nisshi.dev Custom Implementation
This component is a custom implementation for nisshi.dev. It uses @sparkjsdev/spark and React Three Fiber.
Displays 3D Gaussian Splatting scenes. Supports .ply, .spz, .splat, .ksplat, and .sog formats.
| Prop | Type | Required | Description |
|---|---|---|---|
| src | string | ✅ | Splat file path |
| alt | string | - | Model description (for accessibility) |
| children | ReactNode | - | Caption |
| height | string | number | - | Viewer height (default: "350px") |
| autoRotate | boolean | - | Auto-rotate (default: false) |
| autoRotateSpeed | number | - | Auto-rotate speed (default: 1.0) |
| scale | number | - | Model scale (default: 1) |
| cameraPosition | [number, number, number] | - | Initial camera position (default: [0, 0, 5]) |
| debug | boolean | - | Show debug info (default: false) |
<SplatViewer src="/splats/scene.spz" alt="3D scanned scene">
Gaussian Splat scene (drag to rotate, scroll to zoom)
</SplatViewer>Workshop scene captured with Gaussian Splatting
TilesViewer (3D Tiles)
nisshi.dev Custom Implementation
This component is a custom implementation for nisshi.dev. It uses 3d-tiles-renderer and React Three Fiber. It supports PLATEAU, Google Photorealistic 3D Tiles, Cesium Ion, and more.
Displays OGC 3D Tiles format 3D city models and terrain data.
| Prop | Type | Required | Description |
|---|---|---|---|
| src | string | - | Tileset JSON URL |
| cesiumIon | { assetId: string } | - | Cesium Ion configuration |
| googleCloud | {} | - | Google Cloud configuration |
| alt | string | - | Model description (for accessibility) |
| children | ReactNode | - | Caption |
| height | string | number | - | Viewer height (default: "400px") |
| camera | CameraConfig | - | Camera settings (latitude, longitude, altitude) |
| region | RegionConfig | - | Region restriction (loads only tiles within the specified range) |
| debug | boolean | - | Show debug info (default: false) |
Specify one of src, cesiumIon, or googleCloud.
<TilesViewer
cesiumIon={{ assetId: "2602291" }}
camera={{ lat: 35.6569, lon: 139.7464, height: 294 }}
region={{ lat: 35.6616, lon: 139.7433, radius: 500 }}
alt="PLATEAU Tokyo 3D model"
>
PLATEAU 3D city model (drag to rotate, scroll to zoom)
</TilesViewer>PLATEAU Tokyo 3D city model (around Tokyo Tower)
PanoramaViewer (Panoramic Images)
nisshi.dev Custom Implementation
This component is a custom implementation for nisshi.dev. It uses react-photo-sphere-viewer.
Displays panoramic images in a 360° viewer. You can move the viewpoint by dragging and zoom with the scroll wheel.
| Prop | Type | Required | Description |
|---|---|---|---|
| src | string | ✅ | Panoramic image path |
| type | "equirectangular" | "cylindrical" | - | Projection type (default: "equirectangular") |
| alt | string | - | Image description (for accessibility) |
| children | ReactNode | - | Caption |
| autoRotateSpeed | number | - | Auto-rotate speed (RPM, default: 1.0) |
| defaultZoomLevel | number | - | Default zoom level (0-100, default: 30) |
| defaultYaw | number | - | Default horizontal angle (degrees, 0-360, default: 0) |
The type prop switches between projection modes. Equirectangular is a full spherical panorama where you can look in all directions, while Cylindrical is a horizontal-only panorama like iPhone's panorama photos.
<PanoramaViewer src="/images/panorama-360.jpg" alt="360° panorama">
Equirectangular format - look around in all directions
</PanoramaViewer>
<PanoramaViewer type="cylindrical" src="/images/panorama.jpg" alt="Panorama">
Cylindrical format - look around horizontally only
</PanoramaViewer>Equirectangular format - look around in all directions
Cylindrical format - look around horizontally only
VR180Viewer (VR180 Video)
nisshi.dev Custom Implementation
This component is a custom implementation for nisshi.dev. It uses React Three Fiber.
Displays Side-by-Side (SBS) format VR180 video projected onto a 180-degree hemisphere. Drag to rotate the viewpoint, and click to play/pause.
| Prop | Type | Required | Description |
|---|---|---|---|
| src | string | ✅ | VR180 video file path (SBS format) |
| alt | string | - | Video description (for accessibility) |
| children | ReactNode | - | Caption |
| height | string | number | - | Viewer height (default: "500px") |
| muted | boolean | - | Muted (default: true) |
| loop | boolean | - | Loop playback (default: true) |
<VR180Viewer src="/content/blog/example/vr180-video.mp4" alt="VR180 video">
VR180 video (drag to look around, click to play/pause)
</VR180Viewer>VR180 video (drag to look around, click to play/pause)
YouTube Videos
nisshi.dev Custom Implementation
This component is a custom implementation for nisshi.dev. It uses @next/third-parties/google.
Writing a YouTube URL on its own line automatically creates an embedded player.
https://www.youtube.com/watch?v=Vxtr-JzaePYX (Twitter) Posts
nisshi.dev Custom Implementation
This component is a custom implementation for nisshi.dev. It uses react-tweet.
X post URLs are displayed as embedded posts.
https://x.com/nisshi_dev/status/1697919798217200076MediaGrid
nisshi.dev Custom Implementation
This component is a custom implementation for nisshi.dev.
A grid component for arranging media elements side by side. It supports images, Tweets, YouTube embeds, LinkCards, and more.
| Prop | Type | Required | Description |
|---|---|---|---|
| cols / columns | 2 | 3 | 4 | - | Number of columns (default: 2) |
| gap | "sm" | "md" | "lg" | - | Gap between elements (default: "md") |
| align | "start" | "center" | - | Vertical alignment (default: "start") |
| children | ReactNode | ✅ | Child elements |
<MediaGrid cols={2}>


</MediaGrid>3-Column Layout
<MediaGrid cols={3} gap="sm">



</MediaGrid>Combined with Figure
<MediaGrid>
<Figure caption="Real venue">

</Figure>
<Figure caption="VR venue">

</Figure>
</MediaGrid>DesktopOnly
nisshi.dev Custom Implementation
This component is a custom implementation for nisshi.dev.
A wrapper that restricts content to desktop only when it could cause crashes on mobile due to memory limitations (especially iOS Safari). On mobile, it displays a fallback link instead.
| Prop | Type | Required | Description |
|---|---|---|---|
| children | ReactNode | ✅ | Content to display on desktop |
| fallbackUrl | string | ✅ | Fallback URL for mobile |
| fallbackTitle | string | - | Fallback title for mobile |
| width | string | number | - | Width |
| height | string | number | - | Height |
<DesktopOnly
fallbackUrl="https://example.com/embed"
fallbackTitle="Embedded content"
>
<iframe src="https://example.com/embed" />
</DesktopOnly>Mermaid (Diagrams)
nisshi.dev Custom Implementation
This component is a custom implementation for nisshi.dev. It uses mermaid.
You can draw flowcharts and diagrams using Mermaid syntax.
```mermaid
graph TD
A[Start] --> B{Condition}
B -->|Yes| C[Process A]
B -->|No| D[Process B]
C --> E[End]
D --> E
```Sequence Diagram
Tables
| Feature | Description | Status |
|---------|-------------|--------|
| MDX | Extended Markdown syntax | ✅ |
| Syntax Highlighting | Code coloring | ✅ |
| Math | Mathematical expressions via KaTeX | ✅ || Feature | Description | Status |
|---|---|---|
| MDX | Extended Markdown syntax | ✅ |
| Syntax Highlighting | Code coloring | ✅ |
| Math | Mathematical expressions via KaTeX | ✅ |
Frontmatter (Article Metadata)
Each article starts with metadata at the top.
---
title: Article Title
description: Article description (used for SEO and OGP)
subtitle: Subtitle (optional)
type: tech # tech, report, tutorial, idea, diary
topics: ["Next.js", "React"] # Tags
createdAt: 2025-01-01
published: true
featured: false # Featured article
archived: false # Archived
ogImage: /og/custom-og.png # Custom OGP image (auto-generated if omitted)
---References
When new components are added, this page will be updated accordingly. If you have ideas like "How about adding this component?", feel free to let us know in the comments below!
VRが好きなWebエンジニア。WebXRやVR・機械加工などの技術が好きでものづくりしている。WebXR JPというコミュニティやWeb技術集会というVR空間内の技術イベントを運営中。
Comments
Feel free to share your thoughts or questions about this article