hacomono TECH BLOG

フィットネスクラブ・スクールなど施設・店舗のための会員管理・予約・決済システム「hacomono」 開発チームの技術ブログ

Starlight に触ってみた

こちらの記事はhacomono Advent Calendar 2023の6日目の記事です

フロントエンドテックリードやってます. みゅーとんです.

GitHub の hacomono-lib organization にて, OSS として TypeGuard 関数ライブラリを作っています.
lodash を脱却したい思いで実装していましたが, ある程度実装が固まってきて, もうすぐ v1 をリリースできそうなので, 合わせてドキュメント化をすることにしました.

さて,ドキュメント化フレームワークというと,最近ホットなのは astro のメタフレームワークである,starlight かなと思います.

せっかくなので,触ってみました.

TL; DR

  • Starlight は astro のメタフレームワークで
  • MarkDown / MarkDoc / MDX 標準サポート
  • 導入も実装も超簡単

対象読者

  • ドキュメント化フレームワークを探している
  • Starlight がきになる

本記事で語らないこと

  • Astro とは?
  • Astro の導入
  • 他のドキュメンテーションフレームワークとの違い
  • Starlight の目玉機能: React, Vue などのコンポーネントを MDX で埋め込み描画できる仕組み
    • 今回触ってないため語れないです. 別の機会があれば.

Starlight is 何?

docsourus 等のドキュメンテーションフレームワークの一種で, astro をベースにしています.

astro ベースであるため, astro の以下の恩恵がそのまま享受できます.

  • 完成品が Zero JS の MultiPage Static Site
    • Zero JS のため描画が爆速
  • astro プラグインにより, React や Vue などのコンポーネントをそのまま利用できる.
  • 環境に優しい (こちらのドキュメントより)
    • 他のフレームワークとの 発生する CO2 の比較があったりして, 面白いです.

astro はファイルベースルーティングでページを構築しますが, そのページとするソースコードを MarkDown (MDX, MarkDox) にしたものが Starlight です.

標準となるデザイン (レイアウトや汎用コンポーネントなど) はすべて starlight ライブラリに実装されているため, 基本的にほぼ何も考えなくてもドキュメントを作れてしまいます. (体感)

早速立ち上げてみる

公式のマニュアルに従って, テンプレートプロジェクトをローカルに作ってみます.

作業は簡単で、 npm create astro@latest -- --template starlight を実行すれば良いだけのようです.

インストール中, 表情がころころ変わります. かわいいですね.

インストール直後の状態で astro dev で立ち上げてみるとこの画面が出てきます.

さて, ここでの利用は OSS でのドキュメンテーションであるため, ドキュメントのためのコードはすべて docs フォルダ配下になります.
astro プロジェクトのルートを docs 配下に移動し, コマンドを astro dev --root ./docs にすることで, docs 配下がルートでも実行ができます.

ドキュメントを書いていく

まず, サイドメニューの構成をイメージしながら, 自動生成された astro.config.mjs を編集します.
テンプレートの時点である程度の値が埋まっているので, それに習って記載していけば困ることはないはずです.
自作のタイプガードライブラリでは, コンセプトなどのドキュメントを Introduction として, 各関数の解説を Reference として用意したいので, config は以下のようになりました.

import { defineConfig } from 'astro/config'
import starlight from '@astrojs/starlight'

export default defineConfig({
  integrations: [
    starlight({
      title: 'type-assurer',
      social: {
        github: 'https://github.com/hacomono-lib/type-assurer',
      },
      sidebar: [
        {
          label: 'Introduction',
          items: [
            { label: 'Getting Started', link: '/guides/start' },
            { label: 'Concepts', link: '/guides/concepts' },
          ]
        },
        {
          label: 'Reference',
          autogenerate: { directory: 'reference' }
        }
      ]
    })
  ]
})

同時に <ROOT>/content/docs/guides/start.md <ROOT>/content/docs/concepts.md を作って, 本文を記載していきます. 長くなるので本文は省略します.

多言語対応も標準搭載

せっかくなので, その場の勢いで多言語対応を済ませておきます.
config を以下のように変更しました.

import { defineConfig } from 'astro/config'
import starlight from '@astrojs/starlight'

export default defineConfig({
  integrations: [
    starlight({
      title: 'type-assurer',
      social: {
        github: 'https://github.com/hacomono-lib/type-assurer',
      },
      defaultLocale: 'root',
      locales: {
        root: {
          label: 'English',
          lang: 'en-US'
        },
        'jp': {
          label: '日本語',
          lang: 'ja-JP'
        }
      },
      sidebar: [
        {
          label: 'Home',
          translations: { 'ja-JP': 'ホーム' },
          link: '/'
        },
        {
          label: 'Introduction',
          collapsed: false,
          items: [
            { label: 'Getting Started', link: '/guides/start', translations: { 'ja-JP': '始める' }, },
            { label: 'Concepts', link: '/guides/concepts', translations: { 'ja-JP': 'コンセプト' } },
          ]
        },
        {
          label: 'Reference',
          autogenerate: { directory: 'reference', collapsed: false }
        }
      ]
    })
  ]
})

これに合わせて, フォルダ構成を以下のように変更します.

言語違いの同名ドキュメントができてしまいました.
まぁ、ドキュメントで多言語対応となると、この構成はきっと妥当でしょう. おそらく.

この設定がおわると, ヘッダーに言語選択の項目が生まれます. 爆速ですね.

index.mdx を手直し

mdx は MarkDown に JSX のような記法を追加したような記述になります.
トップページには hero と カードがありましたが, この実装を参考に 以下のように直してみます

---
title: type-assurer
description: A type guard / type assertion for TypeScript
template: splash
hero:
  tagline: A type guard / type assertion for TypeScript
  actions:
    - text: Getting Started
      link: /guides/start/
      icon: right-arrow
      variant: primary
    - text: Repository
      link: https://github.com/hacomono-lib/type-assurer
      icon: github
---

import { Card, CardGrid } from '@astrojs/starlight/components';

## Concepts

<CardGrid>
  <Card title="TypeScript-First" icon="approve-check">
    TypeScript first implementation with accurate type inference.
  </Card>

  <Card title="Tree Shaking" icon="approve-check">
    ES Modules and TypeScript allow for tree-shaking, so you can optimize your bundle size.
  </Card>

  <Card title="No External Dependencies" icon="approve-check">
    No external dependencies, so you don't have to worry about security vulnerabilities.
  </Card>

  <Card title="many types of guard utilities" icon="approve-check">
    7 types of guard, 2 types of assertion utilities are provided.
  </Card>
</CardGrid>

Card, CardGrid は starlight の標準コンポーネントで, 以下のページで解説されています.

たったこれだけの記述で, 以下のようなトップページができます.

十分きれいです.

references/isString.md を書いてみる

サポートする関数のリファレンスを 1 つ書いてみます.
とりあえず, content/docs/references/isString.md をはやして、以下のように書いてみます.

---
title: isString
description: A Type Guard function that checks if a value is a string.
---
A Type Guard function that checks if a value is a string.

## Usage

```typescript
import { isString } from 'type-assurer';

isString(''); // true
isString('foo'); // true
isString(0); // false
isString(null); // false
isString(undefined); // false
isString({}); // false
isString(new String()); // false
```

保存が完了すると, サイドバーにすでに isString が現れています.

本文はこんな感じ

体裁が整っているし, code block の syntax highlight もちゃんと効いています.
もう, ここまでお膳立てされると, 爆速でドキュメント書けちゃいますね.

まとめ

今回は個人的に気になっていた starlight の導入を試してみました.
実装が完了したら, type-assurer を v1 として合わせて公開予定です.
また、その際には GitHub Pages として publish する方法もブログ記事として公開しようかなと考えています.

触ってみた感じ, 特にハマるところはなく, すべてがスムーズに導入できました.
開発体験がとても良い, おすすめできるフレームワークでした.

hacomono のマニュアルも全部 starlight で書きたいなぁ・・


株式会社hacomonoでは一緒に働く仲間を募集しています!
採用情報や採用ウィッシュリストも是非ご覧ください!