Swagger UIに飽きた?Stoplight ElementsでAPIドキュメントをモダンにしよう【Gin対応・他ライブラリ比較あり】

に公開

APIドキュメント、何で表示していますか?

「とりあえずSwagger UIでいいか」
「Gin使ってるし、gin-swaggerでサクッと出すか」

そんな感じで、なんとなくSwagger UIを選んでいませんか?もちろんSwagger UIは素晴らしいツールですし、機能的には申し分ないんですが、UIが少し古めかしく感じたり、StripeやTwilioのような3ペインのモダンなレイアウトに憧れたりすることはありませんか?

今回は、そんなあなたにぴったりな Stoplight Elements をご紹介します。日本語の情報がまだ少ないので、公式サイトからの引用を交えつつ、実際のUbuntu環境でのベンチマーク(重さや処理速度の比較)や、GinのSwagger UIとの比較まで、たっぷりとお届けします!


Stoplight Elementsとは?

Stoplight Elementsは、OpenAPI(旧Swagger)ドキュメントを美しく、インタラクティブに表示するためのオープンソースのUIコンポーネントです。

公式サイトでは以下のように説明されています。

"Build highly customized, interactive API Docs with embeddable web components generated from OpenAPI documents."
Stoplight Elements 公式サイト

(意訳:OpenAPIドキュメントから生成されるWebコンポーネントを使って、高度にカスタマイズされたインタラクティブなAPIドキュメントを構築できます。)

また、GitHubのリポジトリには以下の説明があります。

"Build beautiful, interactive API Docs with embeddable React or Web Components, powered by OpenAPI and Markdown."
stoplightio/elements - GitHub

(意訳:ReactまたはWebコンポーネントとして組み込み可能な、OpenAPIとMarkdownを活用した美しくインタラクティブなAPIドキュメントを構築できます。)

最大の特徴は、StripeやTwilioのような 3カラム(3ペイン)レイアウト を簡単に実現できることです。左にナビゲーション、中央にエンドポイントの説明、右にリクエスト/レスポンスの例とTry Itパネルが配置される、あのモダンなスタイルです。

主な特徴

公式サイトでは、以下の特徴が挙げられています。[1]

特徴 説明
Delightful developer experience カスタマイズ可能なサイドバーと3カラムレイアウトで、開発者がAPIを素早く見つけて利用できる
Powered by standards OpenAPIとJSON Schemaを活用し、動的なペイロードにも対応した美しいドキュメントを生成
Interactive API console ドキュメント内でリクエストを送信・レスポンスを確認できる「Try It」機能
Code samples cURL、Python、Ruby、Javaなど多言語のコードサンプルを自動生成
Enhanced markdown support タブ、コールアウト、JSONの埋め込みなどに対応したStoplight独自のMarkdown拡張
Easy to set up ビルドステップ不要。Webコンポーネントとして任意のフレームワークで利用可能

採用実績

Spotifyが開発者向けサイトの「Get Artist」ドキュメントにStoplight Elementsを採用しているほか、Dyteなど多くの企業が利用しています。[2]


実際のUIを見てみよう

まず、百聞は一見に如かず。実際のUIを見比べてみましょう。

従来のSwagger UI(gin-swagger)

GinとSwaggerの組み合わせでよく使われる swaggo/gin-swagger を使ったUIです。

エンドポイントが縦に並び、クリックするとアコーディオン形式で詳細が開きます。

機能的ですが、情報量が多くなると少し見づらくなることも。

特徴:

  • シンプルな1カラムレイアウト
  • アコーディオン形式でエンドポイントを展開
  • 長年使われてきた安定感

Stoplight Elements

一方、Stoplight Elementsの3カラムレイアウトはこちらです。

左サイドバーでAPIの全体像を把握しながら、中央で詳細な説明を読み、右パネルでリアルタイムにAPIリクエストを試せます。

特徴:

  • 3カラムレイアウト(サイドバー + 説明 + Try It)
  • レスポンスのスキーマが見やすく整理されている
  • コードサンプルが多言語で自動生成される
  • OpenAPI 3.1対応

他パッケージとの比較(実測ベンチマーク)

「他にもRedocやScalarがあるじゃないか」と思うかもしれません。そこで、実際のUbuntu環境(Node.js v22.13.0)で、代表的なAPIドキュメントUIライブラリのインストールサイズとバンドルサイズを実測してみました。

比較対象パッケージ

パッケージ名 バージョン 特徴
@stoplight/elements v9.0.16 今回の主役。3カラムレイアウト対応
swagger-ui-dist v5.32.2 Swagger UI公式。最も普及している
redoc v2.5.2 シンプルで軽量。2カラムレイアウト
@scalar/api-reference v1.51.0 新興。モダンなデザイン

1. インストールサイズ(node_modulesの重さ)

プロジェクトに組み込む際の重さ(依存関係を含む)です。以下はUbuntu上で npm install した際の実測値です。

# 計測コマンド
du -sh node_modules
パッケージ名 node_modulesサイズ(実測)
redoc 82 MB
@stoplight/elements 125 MB
swagger-ui-dist 190 MB
@scalar/api-reference 481 MB

Redocが最も軽量です。Stoplight Elementsは125MBと中程度、Scalarは依存関係が非常に多く481MBとかなり重めです。

2. バンドルサイズ(ブラウザに配信されるファイルサイズ)

実際にブラウザで読み込まれる際のファイルサイズ(Minify済みのJS/CSS)です。Ubuntu上で実測しました。

# ファイルサイズの計測
ls -lh <bundle-file>

# gzip後サイズの計測
gzip -c <bundle-file> | wc -c
パッケージ名 JSサイズ (Minified) gzip後 CSSサイズ
redoc (standalone.js) 919 KB 281 KB (JSに内包)
swagger-ui-dist (bundle.js) 1.5 MB 403 KB 175 KB
@stoplight/elements (web-components.min.js) 2.0 MB 583 KB 291 KB
@scalar/api-reference (standalone.js) 3.8 MB 1.08 MB (JSに内包)

Stoplight Elementsは、ReactベースのWebコンポーネントとして提供されているため、Swagger UIやRedocと比べるとバンドルサイズはやや大きめです。ただし、gzip後は583KBと、昨今のネットワーク環境であれば十分に許容範囲内です。CDNを使えばキャッシュも効くので、実際の体感速度はそれほど気になりません。

3. 機能比較

機能 Stoplight Elements Swagger UI Redoc Scalar
3カラムレイアウト
Try It(APIリクエスト送信) ❌(有料版のみ)
OpenAPI 3.1対応
Webコンポーネント対応
Markdown記事サポート ✅(Dev Portal)
多言語コードサンプル
ライセンス Apache 2.0 Apache 2.0 MIT MIT

GinのSwagger UIからStoplight Elementsへ移行する

ここからは、実際にGinで作ったAPIにStoplight Elementsを組み込む方法を解説します。

現状のGin + gin-swaggerの構成

Ginを使っている場合、swaggo/gin-swagger を使ってSwagger UIを表示するのが定番です。

# swagコマンドのインストール
go install github.com/swaggo/swag/cmd/swag@latest

# gin-swaggerのインストール
go get -u github.com/swaggo/gin-swagger
go get -u github.com/swaggo/files
// main.go
package main

import (
    "net/http"

    "github.com/gin-gonic/gin"
    swaggerFiles "github.com/swaggo/files"
    ginSwagger "github.com/swaggo/gin-swagger"
    _ "yourproject/docs"  // swagで生成したdocsを読み込む
)

// @title Sample API
// @version 1.0
// @description This is a sample server.
// @host localhost:8080
// @BasePath /api/v1

// PingExample godoc
// @Summary ping example
// @Description do ping
// @Tags example
// @Produce json
// @Success 200 {string} string "helloworld"
// @Router /example/helloworld [get]
func Helloworld(c *gin.Context) {
    c.JSON(http.StatusOK, "helloworld")
}

func main() {
    r := gin.Default()
    
    // Swagger UIのルートを追加
    r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
    
    r.Run(":8080")
}
# swagコマンドでOpenAPIドキュメントを生成
swag init

# サーバー起動後、以下のURLでSwagger UIにアクセス
# http://localhost:8080/swagger/index.html

これで http://localhost:8080/swagger/index.html にアクセスすると、おなじみのSwagger UIが表示されます。

Stoplight Elementsを組み込む方法

Stoplight Elementsを使う場合、OpenAPIドキュメント(JSONまたはYAML)さえあれば、HTMLファイルを1つ追加するだけで完了です。

方法1: HTMLファイルを追加する(最も簡単)

// main.go に追加
r.GET("/docs", func(c *gin.Context) {
    c.Data(200, "text/html; charset=utf-8", []byte(stoplightHTML))
})

// OpenAPIのJSONを提供するエンドポイント(swaggoが生成したものを使う)
r.GET("/docs/openapi.json", func(c *gin.Context) {
    c.File("./docs/swagger.json")
})
// HTMLテンプレート(定数として定義)
const stoplightHTML = `<!doctype html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>API Documentation</title>
    <script src="https://unpkg.com/@stoplight/elements/web-components.min.js"></script>
    <link rel="stylesheet" href="https://unpkg.com/@stoplight/elements/styles.min.css">
    <style>html, body { height: 100%; margin: 0; }</style>
  </head>
  <body>
    <elements-api
      apiDescriptionUrl="/docs/openapi.json"
      router="hash"
      layout="sidebar"
    />
  </body>
</html>`

これだけです!http://localhost:8080/docs にアクセスすると、Stoplight ElementsのモダンなUIでAPIドキュメントが表示されます。

方法2: 静的ファイルとして配置する

# staticディレクトリを作成
mkdir -p static/docs
<!-- static/docs/index.html -->
<!doctype html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>API Documentation</title>
    <script src="https://unpkg.com/@stoplight/elements/web-components.min.js"></script>
    <link rel="stylesheet" href="https://unpkg.com/@stoplight/elements/styles.min.css">
    <style>html, body { height: 100%; margin: 0; }</style>
  </head>
  <body>
    <elements-api
      apiDescriptionUrl="/docs/openapi.json"
      router="hash"
      layout="sidebar"
    />
  </body>
</html>
// main.go
r.Static("/docs", "./static/docs")
r.GET("/docs/openapi.json", func(c *gin.Context) {
    c.File("./docs/swagger.json")
})

方法3: npmパッケージとして使う(Reactプロジェクト)

Reactを使っている場合は、コンポーネントとして組み込めます。

npm install @stoplight/elements
import { API } from '@stoplight/elements';
import '@stoplight/elements/styles.min.css';

const ApiDocs = () => (
  <div style={{ height: '100vh' }}>
    <API
      apiDescriptionUrl="/docs/openapi.json"
      router="hash"
      layout="sidebar"
    />
  </div>
);

設定項目(プロパティ)完全まとめ

<elements-api> タグ(または <API> コンポーネント)に渡せる全設定項目です。[3]

基本設定

プロパティ名 説明 デフォルト値
apiDescriptionUrl string OpenAPIドキュメント(JSON/YAML)のURL。http://https://$refを含むドキュメントに対応 (必須)
apiDescriptionDocument string/object OpenAPIドキュメントの文字列またはオブジェクトを直接渡す場合に使用
basePath string router: 'history' 使用時に、ドキュメントがサブディレクトリにある場合のベースパス(例:/docs/api

レイアウト設定

プロパティ名 説明 デフォルト値
layout string レイアウトの指定。3種類から選択 sidebar
logo string サイドバー上部に表示するロゴ画像のURL

layout の選択肢は以下の3つです。

公式ドキュメントには次のように記載されています。[3:1]

  • sidebar — (default) Three-column design with a sidebar that can be resized.
  • responsive — Like sidebar, except at small screen sizes it collapses the sidebar into a drawer that can be toggled open.
  • stacked — Everything in a single column, making integrations with existing websites that have their own sidebar or other columns already.
  • sidebar(デフォルト): 3カラムデザイン。サイドバーのサイズ変更が可能
  • responsive: sidebar と同様だが、小さい画面ではサイドバーがドロワーに切り替わる
  • stacked: 1カラム。既存のサイドバーを持つCMSへの組み込みに最適

ルーター設定

プロパティ名 説明 デフォルト値
router string ナビゲーションの方式 history

router の選択肢は以下の4つです。

  • history — (default) uses the HTML5 history API to keep the UI in sync with the URL.
  • hash — uses the hash portion of the URL to keep the UI in sync with the URL.
  • memory — keeps the history of your "URL" in memory (doesn't read or write to the address bar).
  • static — renders using the StaticRouter which can help render pages on the server.
  • history(デフォルト): HTML5 History APIを使用。通常のURLでナビゲーション
  • hash: URLのハッシュ部分を使用。SPAや静的サイトに向いている
  • memory: URLを変更せずにメモリ内でナビゲーション
  • static: StaticRouterを使用。サーバーサイドレンダリング(SSR)に対応

表示制御

プロパティ名 説明 デフォルト値
hideInternal boolean x-internal でマークされたコンテンツを非表示にする false
hideTryIt boolean 「Try It」機能を完全に非表示にする false
hideTryItPanel boolean Try Itパネルを非表示にしつつ、リクエストサンプルは表示する(hideTryIt: false が前提) false
hideSchemas boolean sidebar レイアウト使用時に、目次からスキーマを非表示にする false
hideExport boolean ドキュメント概要セクションの「Export」ボタンを非表示にする false

Try It設定

プロパティ名 説明 デフォルト値
tryItCorsProxy string Try It機能でリクエストを送信する際に使用するCORSプロキシのURL
tryItCredentialsPolicy string Try It機能のクレデンシャルポリシー。omit(デフォルト)、includesame-origin から選択 omit

コマンドまとめ

インストール

# npm
npm install @stoplight/elements

# yarn
yarn add @stoplight/elements

# pnpm
pnpm add @stoplight/elements

CDNで使う(ビルド不要)

<!-- JSの読み込み -->
<script src="https://unpkg.com/@stoplight/elements/web-components.min.js"></script>

<!-- CSSの読み込み -->
<link rel="stylesheet" href="https://unpkg.com/@stoplight/elements/styles.min.css">

バージョンを固定して使う(推奨)

<!-- バージョンを固定する場合(例:v9.0.16) -->
<script src="https://unpkg.com/@stoplight/elements@9.0.16/web-components.min.js"></script>
<link rel="stylesheet" href="https://unpkg.com/@stoplight/elements@9.0.16/styles.min.css">

Ginプロジェクトでのswag操作

# swagコマンドのインストール
go install github.com/swaggo/swag/cmd/swag@latest

# OpenAPIドキュメントの生成(プロジェクトルートで実行)
swag init

# 特定のファイルを指定して生成
swag init -g main.go --output docs

# ネストしたディレクトリ構成の場合
swag init -g ./cmd/yourapp/main.go -o cmd/docs

# 生成されるファイル
# docs/
# ├── docs.go        # Goのソースコード
# ├── swagger.json   # OpenAPI JSON
# └── swagger.yaml   # OpenAPI YAML

Gin + Stoplight Elementsの完全なサンプルコード

以下は、GinでAPIを作りつつ、Stoplight Elementsでドキュメントを表示する完全なサンプルです。

// main.go
package main

import (
    "net/http"

    "github.com/gin-gonic/gin"
    _ "yourproject/docs"
)

// @title           Sample API
// @version         1.0
// @description     Stoplight Elements デモ用APIサーバー
// @host            localhost:8080
// @BasePath        /api/v1

// User ユーザー情報
type User struct {
    ID    int    `json:"id" example:"1"`
    Name  string `json:"name" example:"John Doe"`
    Email string `json:"email" example:"john@example.com"`
}

// GetUsers ユーザー一覧を取得
// @Summary      List all users
// @Description  Get a list of all users in the system
// @Tags         users
// @Produce      json
// @Success      200  {array}   User
// @Failure      500  {object}  map[string]string
// @Router       /users [get]
func GetUsers(c *gin.Context) {
    users := []User{
        {ID: 1, Name: "John Doe", Email: "john@example.com"},
    }
    c.JSON(http.StatusOK, users)
}

const stoplightHTML = `<!doctype html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>API Docs</title>
    <script src="https://unpkg.com/@stoplight/elements/web-components.min.js"></script>
    <link rel="stylesheet" href="https://unpkg.com/@stoplight/elements/styles.min.css">
    <style>html, body { height: 100%; margin: 0; }</style>
  </head>
  <body>
    <elements-api
      apiDescriptionUrl="/openapi.json"
      router="hash"
      layout="sidebar"
    />
  </body>
</html>`

func main() {
    r := gin.Default()

    // APIルート
    v1 := r.Group("/api/v1")
    {
        v1.GET("/users", GetUsers)
    }

    // OpenAPI JSONを提供
    r.GET("/openapi.json", func(c *gin.Context) {
        c.File("./docs/swagger.json")
    })

    // Stoplight Elements UIを提供
    r.GET("/docs", func(c *gin.Context) {
        c.Data(200, "text/html; charset=utf-8", []byte(stoplightHTML))
    })

    r.Run(":8080")
}
# ドキュメント生成 & サーバー起動
swag init && go run main.go

# アクセス
# APIドキュメント: http://localhost:8080/docs
# OpenAPI JSON:    http://localhost:8080/openapi.json

Swagger UIとの使い分け

では、Swagger UIとStoplight Elements、どちらを使えばいいのでしょうか?

ユースケース 推奨
社内ツール・開発中のAPI確認 Swagger UI(手軽さ優先)
外部公開のAPIドキュメント Stoplight Elements(見た目・UX優先)
既存のCMSやサイトに埋め込む Stoplight Elements(stackedレイアウト)
Markdownドキュメントと組み合わせる Stoplight Elements Dev Portal
最小限の依存関係で使いたい Redoc
バンドルサイズを最小にしたい Redoc

Swagger UIは「とにかく動かしたい」というときに最適です。一方、Stoplight Elementsは「外部の開発者に使ってもらうAPIドキュメントを作りたい」「見た目にこだわりたい」という場合に特に力を発揮します。


まとめ

Stoplight Elementsのポイントをまとめると:

  • 導入は超簡単 — HTMLに2行追加するだけ(CDN利用)
  • 見た目が圧倒的にモダン — 3カラムレイアウトで情報が整理されている
  • Try It機能が充実 — ドキュメント内でAPIリクエストを送信できる
  • Gin + swaggoとの相性も良好 — 既存の swagger.json をそのまま使える
  • バンドルサイズはやや大きめ — 2.0MB(gzip後は約583KB)
  • node_modulesは125MB — Redocの82MBより大きいが、Scalarの481MBよりは軽量

「APIドキュメントのUIをちょっとリッチにしたいな」と思ったら、ぜひStoplight Elementsを試してみてください!既存のSwagger UIから移行するのも、HTMLを1ファイル追加するだけなので、本当に簡単です。


参考リンク

脚注
  1. Stoplight Elements - Explore the benefits of Elements ↩︎

  2. Stoplight Elements - Embed API docs anywhere ↩︎

  3. Elements Configuration Options ↩︎ ↩︎

VeriCerts Tech Blog

Discussion