ホーム 記事一覧 ブック DH週間トピックス 検索 このサイトについて
English
Observable:D3.js作者が作ったデータ可視化ノートブック

Observable:D3.js作者が作ったデータ可視化ノートブック

はじめに Observable(オブザーバブル)は、D3.jsの作者であるMike Bostock(マイク・ボストック)が開発した、JavaScriptベースのデータ分析・可視化ノートブックプラットフォームです。ブラウザ上でリアクティブなコードを記述し、インタラクティブなデータ可視化をすぐに作成できる環境を提供します。 デジタル・ヒューマニティーズ(DH)の分野では、研究データの探索的分析やインタラクティブな可視化の作成において、Observableが強力なツールとして注目されています。 Observableの特徴 リアクティブノートブック Observableのノートブックは、Jupyter Notebookに似た概念ですが、JavaScriptベースでリアクティブな実行モデルを採用しています。 リアクティブ実行:セルの値が変更されると、依存するセルが自動的に再実行される 即時プレビュー:コードを書くとリアルタイムで結果が表示される セル間の依存関係:変数を通じてセル間でデータを共有 インポート機能:他のノートブックからセルを再利用可能 // Observableのセル例 viewof year = Inputs.range([1900, 2025], {step: 1, value: 2000}) Observable Plot Observable Plotは、Observableチームが開発した高レベルの可視化ライブラリです。D3.jsの強力な機能を、より簡潔なAPIで利用できます。 // Observable Plotによるデータ可視化 Plot.plot({ marks: [ Plot.barY(data, {x: "category", y: "count", fill: "type"}), Plot.ruleY([0]) ], color: {legend: true} }) 主な特徴まとめ 特徴 説明 言語 JavaScript / TypeScript 可視化 Observable Plot, D3.js統合 データ入力 CSV, JSON, SQLite, API コラボレーション チーム共有、コメント機能 公開 ノートブックの公開・埋め込み ライセンス ISC License Observable Framework 2024年にリリースされたObservable Frameworkは、データアプリケーションを構築するための静的サイトジェネレーターです。 特徴 データローダー:Python、R、SQL、JavaScriptなど任意の言語でデータを前処理 Markdownベース:MarkdownファイルにJavaScriptコードを埋め込み 静的ビルド:ビルド時にデータを処理し、高速な静的サイトを生成 セルフホスティング:自分のサーバーやCDNにデプロイ可能 # Observable Frameworkの例 const data = await FileAttachment("data/research_data.csv").csv({typed: true}); Plot.plot({ marks: [Plot.dot(data, {x: "year", y: "value", stroke: "category"})] }) DHにおける活用方法 1. テキスト分析の可視化 文学作品の語彙分析、単語頻度の時系列変化、テキスト間の類似度マッピングなどを、インタラクティブな可視化として作成できます。 ...

MapLibre GL JS でカスタムマーカーがズーム時にずれる問題と GeoJSON レイヤーによる解決

MapLibre GL JS でカスタムマーカーがズーム時にずれる問題と GeoJSON レイヤーによる解決

はじめに MapLibre GL JS で地図上にカスタムマーカーを配置する際、maplibregl.Marker に独自の DOM 要素を渡す方法がよく使われる。件数バッジ付きの丸いマーカーなど、CSS で自由にスタイリングできる利点がある。 しかし、この方法にはズーム・パン操作時にマーカーが地図の動きに遅れて追従するという問題がある。特にマーカー数が多い場合やモバイルデバイスでは顕著になり、ズームアウトすると本来陸上にあるべきマーカーが海上に表示されるような視覚的な不整合も起きる。 本記事では、この問題の原因と、GeoJSON ソース + レイヤーを使った根本的な解決方法を解説する。 問題の再現 DOM マーカーによる実装(問題あり) for (const point of dataPoints) { const el = document.createElement('div') Object.assign(el.style, { width: '32px', height: '32px', borderRadius: '50%', backgroundColor: point.color, border: '3px solid white', boxShadow: '0 2px 6px rgba(0,0,0,0.3)', cursor: 'pointer', display: 'flex', alignItems: 'center', justifyContent: 'center', }) // 件数バッジ if (point.count > 1) { const badge = document.createElement('span') badge.style.color = 'white' badge.style.fontSize = '11px' badge.style.fontWeight = 'bold' badge.textContent = String(point.count) el.appendChild(badge) } new maplibregl.Marker({ element: el }) .setLngLat([point.lng, point.lat]) .addTo(map) } この実装では以下の問題が発生する。 症状 ズーム・パン時の遅延: マーカーが地図の動きに 1〜2 フレーム遅れて追従する ズームアウト時の位置ずれ: 沿岸都市のマーカーが海上に表示される パフォーマンス低下: マーカー数が増えると DOM の再配置コストが増大する 原因 maplibregl.Marker は DOM 要素を CSS transform で配置する仕組みになっている。地図がズーム・パンされるたびに、各マーカーの CSS transform を再計算して更新する必要があり、これが WebGL キャンバスの描画と非同期で行われるため、視覚的なずれが生じる。 ...

Astro 4 から 5 へのアップグレード記録

背景 Astro 4 + MDX + Tailwind CSS で構築していたウェブサイトで、pnpm の overrides により astro 5.x が強制的にインストールされる状態になっていました。@astrojs/mdx@2.x(Astro 4 用)と astro 5.x の間で互換性がなく、ビルドが失敗していました。 Package subpath './jsx/renderer.js' is not defined by "exports" in astro/package.json Astro 4 に戻すよりも、Astro 5 へアップグレードする方が合理的と判断し、移行を実施しました。 変更点 1. パッケージの更新 // Before "@astrojs/mdx": "^2.0.0", "astro": "^4.0.3" // After "@astrojs/mdx": "^4.0.0", "astro": "^5.0.0" @astrojs/tailwind と tailwindcss はそのままです。 2. Content Collections の type 指定を削除 Astro 5 では defineCollection の type: "content" が不要になりました。 // Before const news = defineCollection({ type: "content", schema, }); // After const news = defineCollection({ schema, }); 3. entry.slug から entry.id への変更 Astro 5 では Content Collections の slug プロパティが廃止され、id に統一されました。 ...

Three.js + Puppeteer で VRM キャラクターを動かして動画を自動生成する

Three.js + Puppeteer で VRM キャラクターを動かして動画を自動生成する

はじめに 技術ブログの記事を VTuber 風の解説動画に自動変換できたら面白いのでは――そんな思いつきから、Three.js + Puppeteer で VRM キャラクターをフレーム単位でレンダリングし、VOICEVOX の音声とリップシンクさせて動画を生成するパイプラインを作りました。 この記事では、実装で得られた知見とハマりどころを共有します。 全体のパイプライン 処理の流れは以下の通りです。 Markdown 記事を読み込み → LLM(OpenRouter API)でセクション分割された台本を生成 VOICEVOX でセクションごとに音声(WAV)と音素タイミングを生成 Three.js + @pixiv/three-vrm でヘッドレス Chrome 上に VRM モデルを描画し、音素データに基づくリップシンクアニメーションをフレーム連番 PNG として出力 スライド画像を自動生成(HTML → Chrome ヘッドレス → PNG) FFmpeg でスライド背景 + VRM アニメーション + 音声を合成し、MP4 動画を出力 Python スクリプトがオーケストレーション役を担い、VRM レンダリングは Node.js スクリプトを子プロセスとして呼び出す構成です。 使用技術 役割 技術 3D レンダリング Three.js v0.172 VRM 読み込み @pixiv/three-vrm v3.3.3 ヘッドレスブラウザ puppeteer-core (SwiftShader) 音声合成 VOICEVOX Engine (Docker) 動画合成 FFmpeg パイプライン制御 Python VRM モデル AvatarSample_C (VRoid Hub / 無料ライセンス) ヘッドレス Chrome で VRM を読み込む 課題: file:// の CORS 制限 最初の壁は、ヘッドレス Chrome 上で VRM ファイルを読み込む方法でした。ローカルの .vrm ファイルを file:// プロトコルで読もうとすると CORS エラーで弾かれます。 ...

DOCX → TEI/XML 変換ツールに CETEIcean を使ったプレビュー機能を追加した

DOCX → TEI/XML 変換ツールに CETEIcean を使ったプレビュー機能を追加した

はじめに 以前の記事で、DOCX → TEI/XML 変換ツールを紹介しました。TEI Garage API を使ってブラウザだけで Word 文書を TEI/XML に変換できるツールです。 公開後、利用者の方から「変換されたタグが想定どおりに機能するかを視覚的に確認したい」というフィードバックをいただきました。XML のシンタックスハイライト表示だけでは、見出し・注釈・リスト・テーブルなどが実際にどのようにレンダリングされるか確認が難しいためです。 そこで、CETEIcean を使った TEI プレビュー機能を追加しました。 デモサイト: https://tei-converter.pages.dev/ CETEIcean とは CETEIcean は、TEI Consortium が開発している JavaScript ライブラリです。TEI/XML を HTML5 カスタム要素(Custom Elements) に変換し、ブラウザ上でそのまま表示できます。 通常、TEI/XML をブラウザで表示するには XSLT で HTML に変換する必要がありますが、CETEIcean は Web Components の仕組みを利用して、TEI の要素名をそのままカスタム要素として登録します。例えば <p> は <tei-p> に、<head> は <tei-head> に変換されます。 これにより、CSS だけで TEI 要素のスタイルを定義でき、サーバサイドの変換処理が不要になります。 追加した機能 XML / プレビュー タブ切り替え 変換結果の表示エリアに 「XML」と「プレビュー」の2つのタブを追加しました。 XML タブ: 従来どおりのシンタックスハイライト付き XML 表示 プレビュータブ: CETEIcean によるレンダリング結果 タブをクリックするだけで切り替えられます。 ...

TEI Garage APIを使って、DOCX → TEI/XML 変換ツールをブラウザだけで作った

TEI Garage APIを使って、DOCX → TEI/XML 変換ツールをブラウザだけで作った

はじめに TEI (Text Encoding Initiative) は、人文学分野のテキストをデジタルで構造化するための国際標準です。図書館・博物館・学術研究などで利用されていますが、TEI/XML を直接書くにはマークアップの知識が必要で、導入のハードルが高いのが実情です。 そこで活用されるのが、Microsoft Word (.docx) から TEI/XML への変換ツールです。代表的なものに TEI Garage(旧 OxGarage)がありますが、多機能ゆえに UI がやや複雑です。今回、DOCX → TEI/XML の変換に特化した、シンプルなブラウザベースのツールを作成しました。 https://github.com/nakamura196/tei-converter デモサイト: https://tei-converter.pages.dev/ 仕組み TEI Garage は REST API を公開しており、以下のエンドポイントに DOCX ファイルを POST するだけで TEI/XML が返ってきます。 POST https://teigarage.tei-c.org/ege-webservice/Conversions/ docx:application:vnd.openxmlformats-officedocument.wordprocessingml.document/ TEI:text:xml/ 本ツールはこの API を呼び出すフロントエンドです。変換処理自体は TEI Consortium が運営するサーバ上で行われます。 主な機能 ドラッグ & ドロップ .docx ファイルをブラウザにドラッグ & ドロップするだけでアップロードできます。クリックしてファイルを選択することも可能です。 整形済み XML プレビュー 変換結果はインデント付きで整形され、シンタックスハイライト付きで表示されます。タグ名、属性名、属性値がそれぞれ色分けされるため、構造を把握しやすくなっています。 コピー & ダウンロード 結果をワンクリックでクリップボードにコピーしたり、.xml ファイルとしてダウンロードしたりできます。 サンプル DOCX 内蔵 「サンプル .docx で試す」をクリックするだけで、内蔵のサンプルファイルで動作を確認できます。サンプルのダウンロードも可能です。 ...

ethers.js v6 の日本語チュートリアルを作った

ethers.js v6 の日本語チュートリアルを作った

はじめに Ethereum の JavaScript ライブラリである ethers.js の日本語チュートリアルを作成しました。 https://github.com/nakamura196/ethers-ja-tutorial VitePress で静的サイトとしても公開しています。 https://nakamura196.github.io/ethers-ja-tutorial/ 作った背景 ethers.js は Ethereum 開発において最も広く使われているライブラリの一つです。v6 に関する日本語記事は v5 からのマイグレーション解説が中心で、初心者がゼロから学べる体系的なチュートリアルは見当たりませんでした。公式ドキュメントも英語のみのため、日本語で基礎から順を追って学べるチュートリアルを作成しました。 チュートリアルの内容 全 8 章構成で、基礎から実践的な内容までカバーしています。 章 テーマ 内容 1 環境構築 Node.js と ethers.js のインストール 2 プロバイダー Ethereum ネットワークへの接続 3 ウォレット ウォレットの作成と管理 4 ブロックチェーンの読み取り 残高確認・ブロック情報の取得 5 トランザクション送信 ETH の送金 6 スマートコントラクト コントラクトとのやり取り 7 イベント イベントのリスニング 8 ユーティリティ 単位変換・ハッシュなどの便利機能 特徴 すぐに動くサンプルコード付き examples/ ディレクトリに実行可能なサンプルコードを用意しています。 git clone https://github.com/nakamura196/ethers-ja-tutorial.git cd ethers-ja-tutorial npm install node examples/01-connect.mjs たとえば 01-connect.mjs を実行すると、Ethereum メインネットの最新ブロック番号やガス価格が取得できます。 ...

Annotoriousの描画モードがproduction buildでだけ壊れる

Annotoriousの描画モードがproduction buildでだけ壊れる

はじめに ある日、Vercelにデプロイした IIIF アノテーションエディタで、アノテーションが一切付与できなくなっていることに気づきました。ローカルの開発サーバーでは正常に動作するのに、本番環境でだけ描画モードに入れない。コンソールエラーも出ない。UIのボタンは正しく切り替わるのに、画像上でドラッグしても何も起きない——。 原因は、package.json のキャレット指定(^)による Annotorious の自動アップグレードと、v3.7.13 での状態管理ライブラリ移行が webpack の production build で引き起こす不具合でした。 この記事では、調査過程から根本原因の特定、そして得られた教訓までをまとめます。 環境 フレームワーク : Next.js 15 (App Router) 画像ビューア : OpenSeadragon 5 アノテーション : Annotorious v3 (@annotorious/react + @annotorious/openseadragon) バンドラ : webpack(Next.js 内蔵) デプロイ先 : Vercel 症状 本番環境(Vercel)で以下の症状が発生しました。 矩形・ポリゴンの描画ツールボタンをクリックすると、UIの状態は正しく切り替わる (React の state 更新は正常) しかし Annotorious が描画モードに入らない ——カーソルが crosshair に変わらず auto のまま 画像上でクリック&ドラッグしてもアノテーションが作成されない コンソールにエラーは一切表示されない Annotorious のアノテーションレイヤー要素(a9s-gl-canvas)自体は DOM 上に正しく描画されている ローカルの next dev では完全に正常動作するため、再現が困難な状況でした。 調査過程 1. Playwright による自動テスト まず Playwright を使って、デプロイ済みサイトに対する自動テストを実施しました。 ...

RAWGraphs 2.0 の日本語化

RAWGraphs 2.0 の日本語化

はじめに データ可視化ツール RAWGraphs を日本語化し、公開しました。 https://rawgraphs-ja.vercel.app/ RAWGraphsは、複雑なデータを美しいビジュアライゼーションに変換できるオープンソースのWebアプリケーションです。コーディング不要で、CSVやJSONデータをドラッグ&ドロップするだけで、様々なチャートを作成できます。 RAWGraphsとは RAWGraphsは、イタリアのDensityDesign Research Labが開発したデータ可視化ツールです。 https://www.rawgraphs.io/ 主な特徴: コーディング不要 : ブラウザ上でデータをペーストするだけ 多様なチャート : Alluvial Diagram、Treemap、Voronoi Tessellationなど30種類以上 SVGエクスポート : 作成したチャートをSVGやPNG形式でダウンロード可能 プライバシー保護 : データはサーバーに送信されず、ブラウザ内で処理 使用ライブラリ { "i18next": "^21.10.0", "react-i18next": "^11.18.6" } ! 最新版のi18nextではなく、互換性のある旧バージョンを使用しています。RAWGraphsのビルド環境(react-scripts 4.x)がオプショナルチェーニング(?.)構文を完全にサポートしていないためです。 実装手順 1. i18nの初期化 src/i18n.js を作成し、多言語対応の基盤を構築しました。 import i18n from 'i18next' import { initReactI18next } from 'react-i18next' import translationEN from './locales/en/translation.json' import translationJA from './locales/ja/translation.json' const resources = { en: { translation: translationEN }, ja: { translation: translationJA } } const savedLanguage = localStorage.getItem('i18nextLng') || 'ja' i18n .use(initReactI18next) .init({ resources, lng: savedLanguage, fallbackLng: 'en', interpolation: { escapeValue: false } }) i18n.on('languageChanged', (lng) => { localStorage.setItem('i18nextLng', lng) }) export default i18n 2. 翻訳ファイルの構造 src/locales/ ├── en/ │ └── translation.json └── ja/ └── translation.json 翻訳ファイルは、セクションごとに整理しました: ...

Ace.jsでTeXをハイライトする

Ace.jsでTeXをハイライトする

概要 Ace.jsでTeXをハイライトする機会がありましたので、備忘録です。 以下の記事を参考にしました。 https://banatech.net/blog/view/11 参考になりましたら幸いです。 画面例 デモサイト https://nakamura196.github.io/ace_latex/ リポジトリ https://github.com/nakamura196/ace_latex ソースコード <html lang="en"> <head> <title>ACE in Action</title> </head> <body> <div id="editor" style="width: 100%; height: 400px; border: 1px solid gray;"></div> <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.23.2/ace.js" integrity="sha512-oVyp48/610D5Jo577cvp2vX+Fc0kYaI6s2tZRqBRzjZh7+y/vOEHTzUefbXk/B8P0B76bOK3tL1zeF/QcXlyiA==" crossorigin="anonymous" referrerpolicy="no-referrer" ></script> <script> const text = `\\usepackage{hiragino,ryumin,cid} \\usepackage[dvips]{graphics} \\usepackage{multicol} \\begin{document} テキスト \\右注{(サンプル)}テキスト \\end{document}`; const editor = ace.edit("editor"); // editor.setTheme("ace/theme/monokai"); editor.setFontSize(14); editor.getSession().setMode("ace/mode/latex"); editor.getSession().setUseWrapMode(true); editor.getSession().setTabSize(4); editor.$blockScrolling = Infinity; editor.setOptions({ enableBasicAutocompletion: true, enableSnippets: true, }); editor.setValue(text, 1); </script> </body> </html>

Nuxt3 x babylon.jsで.glbファイルをロードする

Nuxt3 x babylon.jsで.glbファイルをロードする

概要 Nuxt3 x babylon.jsにおいて、.glbファイルのロードを試みた際にエラーが発生しましたので、その備忘録です。 エラーの内容 以下のエラーが発生しました。 Unable to load from ./models/test.glb: importScene of undefined from undefined version: undefined, exporter version: undefinedimportScene has failed JSON parse 対応内容 以下を追加でインストールすることで対応できました。 npm install @babylonjs/loaders 結果、以下のようなjsファイルで表示することができました。 import { Engine, Scene, FreeCamera, Vector3, HemisphericLight, SceneLoader, } from "@babylonjs/core"; import "@babylonjs/loaders/glTF"; const myScene = { engine: null, scene: null, // シーンを作成する関数 createScene: function (canvas) { // エンジンとシーンの初期化 const engine = new Engine(canvas); const scene = new Scene(engine); myScene.engine = engine; myScene.scene = scene; // カメラの設定 const camera = new FreeCamera("camera1", new Vector3(0, 5, -10), scene); camera.setTarget(Vector3.Zero()); camera.attachControl(canvas, true); // 光源の設定 new HemisphericLight("light", Vector3.Up(), scene); // GLBモデルの読み込み SceneLoader.Append( "./models/", "test.glb", scene, function (/*newMeshes*/) { // const mesh = scene.meshes[0]; // シーン内のカメラとライトを作成または更新 scene.activeCamera = null; scene.createDefaultCameraOrLight(true); scene.activeCamera.attachControl(canvas, false); } ); // レンダリングループ engine.runRenderLoop(() => { scene.render(); }); }, }; export default myScene; まとめ 同様のエラーでお困りの方の参考になりましたら幸いです。 ...

Fuse.jsを使用した完全不一致検索(GPT-4による解説)

Fuse.jsを使用した完全不一致検索(GPT-4による解説)

はじめに 以前に以下の記事を執筆しましたが、GPT-4による解説の方が有用でしたので紹介します。 完全不一致検索を JavaScript で実装する方法 Fuse.js は、クライアントサイドで動作する軽量なファジーサーチライブラリです。ただし、今回の目的である完全不一致検索 には向いていません。代わりに、JavaScript の Array メソッドを使って簡単に実装できます。 完全不一致検索の例 次の例では、filter メソッドを使って完全不一致検索を行います。 const data = [ { title: 'Example Title 1', content: 'This is an example content for the first item.', }, { title: 'Example Title 2', content: 'This is an example content for the second item.', }, // ... 他のデータ ]; const searchTerm = 'Example Title 1'; const results = data.filter( (item) => item.title !== searchTerm && item.content !== searchTerm ); console.log(results); この例では、data 配列から searchTerm と完全に一致しない要素をフィルタリングしています。title と content の両方が searchTerm と一致しない場合、要素が結果の配列に含まれます。 このように、JavaScript のネイティブな Array メソッドを使って完全不一致検索を実装できます。 ...

Fuse.jsを使用した完全不一致検索の部分的な実現

Fuse.jsを使用した完全不一致検索の部分的な実現

概要 Fuse.jsはJavascript製の検索エンジンです。 https://fusejs.io/ フロントエンドのみで完結するアプリを作成する際の検索エンジンとして重宝しています。 今回、Fuse.jsを用いた完全不一致検索を実現するにあたり、クエリを工夫する必要があったため、その備忘録です。 高度な検索 Fuse.jsでは、完全・部分一致、部分不一致など、多様な検索が可能です。以下のページに記載があります。 https://fusejs.io/examples.html#extended-search また、以下の記事で日本語訳が公開されています。 https://qiita.com/Sashimimochi/items/4972b3dc333c6e5fb866#より高度な検索 ただし、完全不一致検索については、クエリを工夫する必要がありました。 完全不一致検索 例えば、labelというフィールドに「悪党」という文字列を持たない検索は、以下のようなクエリで部分的に実現できました。「悪党で始まらない」または「悪党で終わらない」を検索しています。 { "$or": [ { "label": "!^悪党" # 「悪党で始まらない」 }, { "label": "!悪党$" # 「悪党で終わらない」 } ] } ただし、上記のクエリは完全ではなく、「悪党と悪党」といった値を持つものも除外してしまう点に注意が必要です。 まとめ 誤った理解をしている点もありそうですが、参考になりましたら幸いです。

[TEI x JavaScript] Nuxt3で意図しないWhitespaceを削除する

[TEI x JavaScript] Nuxt3で意図しないWhitespaceを削除する

課題 TEI/XMLファイルを読み込み、JavaScript(Vue.jsなど)で可視化を行う際、意図しないWhitespaceが入ってしまうケースがありました。 具体的には、以下のようなHTMLを書いた場合、 <template> <div> お問い合わせは <a href="#">こちらから</a> お願いします </div> </template> 以下のように表示され、「お問い合わせは こちらから お願いします」と意図しないスペースが入ってしまいました。 この課題に対して、以下のリポジトリで解決策を公開してくださっていました。 https://github.com/aokiken/vue-remove-whitespace ただ私の環境ではNuxt3ではうまく動作させることができなかったため、ソースコードを参考に、Nuxt3へ導入してみました。 以下、この備忘録です。 Nuxt3への導入 plugins/removeWhitespace.tsを作成します。 function isText(node: ChildNode) { return node.nodeType === Node.TEXT_NODE } function trimText(node: NodeListOf<ChildNode>) { Array.from(node).forEach((node) => { if (isText(node) && node.textContent) { node.textContent = node.textContent.trim() return } trimText(node.childNodes) }) } export default defineNuxtPlugin((nuxtApp) => { nuxtApp.vueApp.directive("removeWhitespace", { mounted(el: HTMLElement) { trimText(el.childNodes) }, updated(el: HTMLElement) { trimText(el.childNodes) }, }); }); そして、pages/index.vueなどで、v-remove-whitespaceディレクティブを使用します。 <template> <div v-remove-whitespace> お問い合わせは <a href="#">こちらから</a> お願いします </div> </template> その結果、以下のように、意図しないWhitespaceを削除できました。 まとめ ディレクティブの理解が不十分で誤っている点もあるかと思いますが、参考になりましたら幸いです。 以下、ソースコードとデモサイト(GitHub Pages)です。 ソースコード https://github.com/nakamura196/nuxt3-removeWhitespace デモサイト https://nakamura196.github.io/nuxt3-removeWhitespace/ なお、本題と話がそれますが、nuxt.config.tsを以下のように記述することで、baseURLを指定することができました。 export default defineNuxtConfig({ app: { baseURL: "/nuxt3-removeWhitespace", // /<reponame> }, }); Nuxt3のSSGをGitHub Pagesで公開する際の参考になりましたら幸いです。 ...