MDX Syntax Available on nisshi.dev Blog

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.

storybook.nisshi.dev

Basic Markdown Syntax

Headings

## Heading 2
### Heading 3
#### Heading 4

Text 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
  1. Numbered item 1
  2. Numbered item 2

Blockquotes

> This is a blockquote.
> It can span multiple lines.

This is a blockquote. It can span multiple lines.

External and internal links are displayed differently. External links automatically get an indicator (↗) showing they lead to an external site.

[Google](https://google.com)

Google

[Blog posts](/blog)

Blog posts


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>;
}
```
src/components/Button.tsx
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

main.py
def hello_world():
    print("Hello, World!")

hello_world()
Terminal
npm install my-package
package.json
{
  "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-ui

TypeScript ⇔ 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.

TypeUsage
infoSupplementary information (default)
note / tipAliases for info
warning / warnWarnings and cautions
dangerErrors and critical warnings
successSuccess 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


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/hono
nextjs.org
fumadocs.dev
github.com

Manual Specification

You can also manually specify link card content using the LinkCard component.

PropTypeRequiredDescription
urlstringLink URL
titlestring-Title (skips OGP fetching when specified)
descriptionstring-Description text
imagestring-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: c=±a2+b2c = \pm\sqrt{a^2 + b^2}

Block

```math
E = mc^2
```
E=mc2E = mc^2
```math
\int_{-\infty}^{\infty} e^{-x^2} dx = \sqrt{\pi}
```
ex2dx=π\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.

github.com
![Sample image](https://pbs.twimg.com/media/G0Hwhu-bUAEbQBC?format=jpg&name=small)

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.

PropTypeRequiredDescription
captionReactNodeCaption (text or JSX)
childrenReactNodeChild elements (images, etc.)
classNamestring-Custom class name
<Figure caption="Event venue">
  ![Venue photo](./venue.jpg)
</Figure>

Sample image with a caption

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.

github.com

A video player component.

PropTypeRequiredDescription
srcstringVideo URL
fallbackSrcstring-Fallback video URL
altstring-Alt text (for accessibility)
posterstring-Poster image URL
autoPlayboolean-Auto-play (default: false)
loopboolean-Loop playback (default: false)
mutedboolean-Muted (default: false)
childrenReactNode-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).

github.com

Displays 3D models in GLB/GLTF format. You can rotate, zoom, and pan using camera controls.

PropTypeRequiredDescription
srcstringModel file path
altstring-Model description (for accessibility)
childrenReactNode-Caption
heightstring | number-Viewer height (default: "400px")
autoRotateboolean-Auto-rotate (default: false)
autoRotateSpeednumber-Auto-rotate speed (degrees/sec, default: 30)
arboolean-Enable AR (default: true)
posterstring-Poster image URL
iosSrcstring-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.

github.com

Displays VRM-format 3D avatars. You can rotate, zoom, and pan using OrbitControls.

PropTypeRequiredDescription
srcstringVRM file path
altstring-Model description (for accessibility)
childrenReactNode-Caption
heightstring | number-Viewer height (default: "350px")
autoRotateboolean-Auto-rotate (default: false)
autoRotateSpeednumber-Auto-rotate speed (default: 1.0)
scalenumber-Model scale (default: 1)
cameraPosition[number, number, number]-Initial camera position (default: [0, 1.5, 3])
debugboolean-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.

github.com

Displays 3D Gaussian Splatting scenes. Supports .ply, .spz, .splat, .ksplat, and .sog formats.

PropTypeRequiredDescription
srcstringSplat file path
altstring-Model description (for accessibility)
childrenReactNode-Caption
heightstring | number-Viewer height (default: "350px")
autoRotateboolean-Auto-rotate (default: false)
autoRotateSpeednumber-Auto-rotate speed (default: 1.0)
scalenumber-Model scale (default: 1)
cameraPosition[number, number, number]-Initial camera position (default: [0, 0, 5])
debugboolean-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.

github.com

Displays OGC 3D Tiles format 3D city models and terrain data.

PropTypeRequiredDescription
srcstring-Tileset JSON URL
cesiumIon{ assetId: string }-Cesium Ion configuration
googleCloud{}-Google Cloud configuration
altstring-Model description (for accessibility)
childrenReactNode-Caption
heightstring | number-Viewer height (default: "400px")
cameraCameraConfig-Camera settings (latitude, longitude, altitude)
regionRegionConfig-Region restriction (loads only tiles within the specified range)
debugboolean-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.

github.com

Displays panoramic images in a 360° viewer. You can move the viewpoint by dragging and zoom with the scroll wheel.

PropTypeRequiredDescription
srcstringPanoramic image path
type"equirectangular" | "cylindrical"-Projection type (default: "equirectangular")
altstring-Image description (for accessibility)
childrenReactNode-Caption
autoRotateSpeednumber-Auto-rotate speed (RPM, default: 1.0)
defaultZoomLevelnumber-Default zoom level (0-100, default: 30)
defaultYawnumber-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.

github.com

Displays Side-by-Side (SBS) format VR180 video projected onto a 180-degree hemisphere. Drag to rotate the viewpoint, and click to play/pause.

PropTypeRequiredDescription
srcstringVR180 video file path (SBS format)
altstring-Video description (for accessibility)
childrenReactNode-Caption
heightstring | number-Viewer height (default: "500px")
mutedboolean-Muted (default: true)
loopboolean-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.

github.com

Writing a YouTube URL on its own line automatically creates an embedded player.

https://www.youtube.com/watch?v=Vxtr-JzaePY

X (Twitter) Posts

nisshi.dev Custom Implementation

This component is a custom implementation for nisshi.dev. It uses react-tweet.

github.com

X post URLs are displayed as embedded posts.

https://x.com/nisshi_dev/status/1697919798217200076

MediaGrid

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.

PropTypeRequiredDescription
cols / columns2 | 3 | 4-Number of columns (default: 2)
gap"sm" | "md" | "lg"-Gap between elements (default: "md")
align"start" | "center"-Vertical alignment (default: "start")
childrenReactNodeChild elements
<MediaGrid cols={2}>
  ![Image 1](https://pbs.twimg.com/media/G0Hwhu-bUAEbQBC?format=jpg&name=small)
  ![Image 2](https://pbs.twimg.com/media/G0Hwhu-bUAEbQBC?format=jpg&name=small)
</MediaGrid>

3-Column Layout

<MediaGrid cols={3} gap="sm">
  ![Image 1](https://pbs.twimg.com/media/G0Hwhu-bUAEbQBC?format=jpg&name=small)
  ![Image 2](https://pbs.twimg.com/media/G0Hwhu-bUAEbQBC?format=jpg&name=small)
  ![Image 3](https://pbs.twimg.com/media/G0Hwhu-bUAEbQBC?format=jpg&name=small)
</MediaGrid>

Combined with Figure

<MediaGrid>
  <Figure caption="Real venue">
    ![Real](./real.jpg)
  </Figure>
  <Figure caption="VR venue">
    ![VR](./vr.jpg)
  </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.

PropTypeRequiredDescription
childrenReactNodeContent to display on desktop
fallbackUrlstringFallback URL for mobile
fallbackTitlestring-Fallback title for mobile
widthstring | number-Width
heightstring | 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.

github.com

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 | ✅ |
FeatureDescriptionStatus
MDXExtended Markdown syntax
Syntax HighlightingCode coloring
MathMathematical 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!

nisshi-dev
nisshi-dev

VRが好きなWebエンジニア。WebXRやVR・機械加工などの技術が好きでものづくりしている。WebXR JPというコミュニティやWeb技術集会というVR空間内の技術イベントを運営中。

Comments

Feel free to share your thoughts or questions about this article

Nickname:
Anonymous
Loading comments...