[{"data":1,"prerenderedAt":375},["ShallowReactive",2],{"content-/2026-04-09-diary":3,"all-pages-for-dir":373,"og-image-/2026-04-09-diary":374},{"id":4,"title":5,"body":6,"category":353,"description":354,"extension":355,"meta":356,"navigation":357,"path":358,"project_name":359,"published":360,"publishedAt":361,"seo":362,"stem":363,"tags":364,"todo":371,"updatedAt":371,"__hash__":372},"pages/2026-04/2026-04-09/diary-2026-04-09.md","2026年4月9日の開発日記 - Excel講座の大規模移行とEDINET財務DB構築",{"type":7,"value":8,"toc":341},"minimark",[9,14,18,22,27,30,36,55,66,69,73,76,80,98,106,108,111,297,299,302,326,328,331],[10,11,13],"h1",{"id":12},"_2026年4月9日の開発日記","2026年4月9日の開発日記",[15,16,17],"p",{},"Excel講座の演習移行とUI改善に大半の時間を投下し、並行してEDINET APIの財務データをTurso DBに流し込む仕組みを一から構築した。セッション12件、コミット数も二桁に届いた。",[19,20,21],"h2",{"id":21},"今日やったこと",[23,24,26],"h3",{"id":25},"_1-excel講座コンテンツ移行eurekapu-nuxt4","1. Excel講座コンテンツ移行（eurekapu-nuxt4）",[15,28,29],{},"演習コンポーネント4種（ChatBox、ExcelDownloader、ExerciseRenderer、TheaterViewer exercise対応）を新規作成し、旧演習23件を変換・移行した。演習を関数チャプターから独立させてtocExcelにも登録。Part 2/3/4（わかりやすいExcelの作り方、NG集、命名ルール）もデータファイル→TOC→ページファイルまで一気に通した。",[15,31,32],{},[33,34,35],"strong",{},"主な成果:",[37,38,39,43,46,49,52],"ul",{},[40,41,42],"li",{},"演習Phase 1-4完了（VLOOKUP5件、INDEX-MATCH5件、総合演習4件、実務演習6件ほか）",[40,44,45],{},"SVGチャート33件を一括生成（配色ルール、数値表示のNG/Good対比など）",[40,47,48],{},"WordPressのCDN URL → Cloudflare R2に完全移行（MP4 13件、GIF 14件、SVG 35件ほか）",[40,50,51],{},"Excelショートカット講座を旧59ページ→8ページのMiller Columnに集約して独立移行",[40,53,54],{},"UIレイアウト改善多数（ChatBoxアバター統合、横並びグリッド、theater-articleモード、ブラウザ履歴連動）",[15,56,57,60,61],{},[33,58,59],{},"詳細:"," ",[62,63,65],"a",{"href":64},"/excel-course-migration-ui-improvements","Excel講座の演習移行・SVG33件一括生成・R2メディア完全移行の作業記録",[67,68],"hr",{},[23,70,72],{"id":71},"_2-edinet-api-turso-db構築","2. EDINET API + Turso DB構築",[15,74,75],{},"EDINET APIで会計ソフトAの財務データを取得し、Turso DB（東京リージョン）に格納するPythonスクリプトを新規作成した。libsqlパッケージの選定で三転四転し、Turso CLIのインストールでもPowerShell→ZIP→WSL→Webダッシュボードと迷走した末に着地。",[15,77,78],{},[33,79,35],{},[37,81,82,89,92,95],{},[40,83,84,88],{},[85,86,87],"code",{},"store_to_turso.py"," 新規作成、冪等なINSERT OR REPLACE方式",[40,90,91],{},"Embedded Replicaの動作検証（ローカル読み取りμs vs HTTP経由ms）",[40,93,94],{},"全6エンドポイントからデータ取得、Chart.jsで36チャートのダッシュボードHTML生成",[40,96,97],{},"FY2022の販管費急増の原因分析（CM広告40億、M&A、無形資産の積み上がり）",[15,99,100,60,102],{},[33,101,59],{},[62,103,105],{"href":104},"/edinet-turso-db-setup","EDINET APIで取得した財務データをTurso DBに格納するPythonスクリプトを構築した",[67,107],{},[19,109,110],{"id":110},"今日の試行錯誤",[112,113,114,136],"table",{},[115,116,117],"thead",{},[118,119,120,124,127,130,133],"tr",{},[121,122,123],"th",{},"#",[121,125,126],{},"テーマ",[121,128,129],{},"試したこと",[121,131,132],{},"結果",[121,134,135],{},"気づき",[137,138,139,166,185,204,227,254,280],"tbody",{},[118,140,141,145,148,160,163],{},[142,143,144],"td",{},"1",[142,146,147],{},"libsqlパッケージ選定",[142,149,150,153,154,153,157],{},[85,151,152],{},"libsql-experimental"," → ",[85,155,156],{},"libsql-client",[85,158,159],{},"libsql",[142,161,162],{},"成功",[142,164,165],{},"旧名→新名のリネームでprebuilt wheelが提供されていた",[118,167,168,171,174,177,179],{},[142,169,170],{},"2",[142,172,173],{},"Turso CLIインストール",[142,175,176],{},"PowerShellスクリプト → ZIPダウンロード → WSL",[142,178,162],{},[142,180,181,184],{},[85,182,183],{},"tursodb.exe","はDB本体でCLI管理ツールではなかった。Webダッシュボードで全操作可能",[118,186,187,190,193,196,198],{},[142,188,189],{},"3",[142,191,192],{},"SVGのContent-Type",[142,194,195],{},"R2にアップロードしたSVGが表示されない",[142,197,162],{},[142,199,200,203],{},[85,201,202],{},"Content-Type: image/svg+xml","を明示的に設定する必要があった。CDNキャッシュが古い値を返す問題も",[118,205,206,209,212,215,217],{},[142,207,208],{},"4",[142,210,211],{},"CSP設定",[142,213,214],{},"R2画像が読み込まれない",[142,216,162],{},[142,218,219,222,223,226],{},[85,220,221],{},"img-src","にR2ドメインが未登録だった。",[85,224,225],{},"media-src","には入っていたので動画は通っていた",[118,228,229,232,235,238,240],{},[142,230,231],{},"5",[142,233,234],{},"theaterスクロール",[142,236,237],{},"コンテンツが独立スクロール領域に閉じ込められる",[142,239,162],{},[142,241,242,245,246,249,250,253],{},[85,243,244],{},".theater-stage","の",[85,247,248],{},"overflow","と",[85,251,252],{},"max-height","を段階的に除去。3回やり直した",[118,255,256,259,262,268,270],{},[142,257,258],{},"6",[142,260,261],{},"APIキー更新",[142,263,264,267],{},[85,265,266],{},".env","を更新しても403が出続ける",[142,269,162],{},[142,271,272,275,276,279],{},[85,273,274],{},"load_dotenv()","がキャッシュした古い値を読んでいた。",[85,277,278],{},"override=True","で解決",[118,281,282,285,288,291,294],{},[142,283,284],{},"7",[142,286,287],{},"Excelショートカット講座の混同",[142,289,290],{},"Excel基礎講座のショートカットセクションと混同して作業",[142,292,293],{},"失敗→修正",[142,295,296],{},"旧プロジェクトでは別URLの独立講座。別セッションに引き継いで再実施",[67,298],{},[19,300,301],{"id":301},"今日の学び",[37,303,304,307,310,318],{},[40,305,306],{},"Tursoの無料枠は500DB・9GB・月10億行読み取りで、個人プロジェクトにはかなり太い。Auth Tokenなしではアクセスできないセキュリティモデルも堅い",[40,308,309],{},"R2へのファイルアップロード時はContent-Typeを明示指定しないと、ブラウザがSVGをレンダリングしない",[40,311,312,313,249,315,317],{},"CSPの",[85,314,221],{},[85,316,225],{},"は別ディレクティブなので、動画が通っても画像が通るとは限らない",[40,319,320,322,323,325],{},[85,321,274],{},"はデフォルトで既存の環境変数を上書きしない。",[85,324,266],{},"を更新したらプロセス再起動が確実",[67,327],{},[19,329,330],{"id":330},"関連記事",[37,332,333,337],{},[40,334,335],{},[62,336,65],{"href":64},[40,338,339],{},[62,340,105],{"href":104},{"title":342,"searchDepth":343,"depth":343,"links":344},"",2,[345,350,351,352],{"id":21,"depth":343,"text":21,"children":346},[347,349],{"id":25,"depth":348,"text":26},3,{"id":71,"depth":348,"text":72},{"id":110,"depth":343,"text":110},{"id":301,"depth":343,"text":301},{"id":330,"depth":343,"text":330},"diary","Excel講座の演習23件移行・SVG33件生成・R2メディア完全移行・ショートカット講座59→8ページ集約と、EDINET APIの財務データをTurso DBに格納する仕組みを構築した1日","md",{},true,"/2026-04-09-diary","daily-log",false,"2026-04-09T00:00:00.000Z",{"title":5,"description":354},"2026-04/2026-04-09/diary-2026-04-09",[365,366,367,368,369,370],"日記","eurekapu-nuxt4","Excel講座","EDINET API","Turso","Cloudflare R2",null,"d0qc2Y-CyrvOExu_qhP8-h6lnEYdTOhib9147HsIvvs",[],"https://log.eurekapu.com/favicon.svg",1775770074033]