<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[morimo's blog]]></title><description><![CDATA[morimo のブログ]]></description><link>https://blog.morimo.dev</link><generator>RSS for Node</generator><lastBuildDate>Sun, 19 Jul 2026 07:23:22 GMT</lastBuildDate><atom:link href="https://blog.morimo.dev/rss.xml" rel="self" type="application/rss+xml"/><pubDate>Fri, 03 Oct 2025 10:22:00 GMT</pubDate><language><![CDATA[ja]]></language><item><title><![CDATA[2025-10-03]]></title><description><![CDATA[<h2>やったこと</h2>
<ul>
<li>HTML, CSSを教えた
<ul>
<li>色変わったり、配置変わったりで驚いてて、自分もこうだったな～と思った</li>
<li>興味持って続けてくれるとうれしいなあ！</li>
</ul>
</li>
<li>ハンバーグ食べた
<ul>
<li>和風、大根おろしが合ってうまかった</li>
</ul>
</li>
<li>お昼寝した</li>
<li>星作った
<ul>
<li><a href="https://xn--j9jkn9872atgp.jp/1125">https://工作ねっと.jp/1125</a></li>
</ul>
</li>
</ul>
]]></description><link>https://blog.morimo.dev/posts/106-2025-10-03</link><guid isPermaLink="false">https://blog.morimo.dev/posts/106-2025-10-03</guid><pubDate>Fri, 03 Oct 2025 10:22:00 GMT</pubDate></item><item><title><![CDATA[Teams AI Library v2 で Teams アプリを作る]]></title><description><![CDATA[<p>v2 で作る</p>
<p><a href="https://github.com/microsoft/teams-ai/tree/v2-preview">https://github.com/microsoft/teams-ai/tree/v2-preview</a></p>
<h2>準備</h2>
<ul>
<li><a href="https://microsoft.github.io/teams-ai/typescript/getting-started">https://microsoft.github.io/teams-ai/typescript/getting-started</a></li>
</ul>
<h3>Prerequisites</h3>
<ul>
<li>Node.js v20↑</li>
</ul>
<h3>Install the Teams CLI</h3>
<pre><code class="language-text">npm install -g @microsoft/teams.cli@preview
</code></pre>
<p><code>teams &#x3C;command></code> 系コマンドはこのCLIを使ってる。グローバルインストールする必要はなくて、都度 <code>npx @microsoft/teams.cli@preview &#x3C;command></code> で実行してもOK。</p>
<h3>プロジェクト作成</h3>
<pre><code class="language-text">teams new typescript &#x3C;アプリ名>
</code></pre>
<p>オウム返しするだけのアプリが作成される。</p>
<h2>デバッグ</h2>
<h3>Dev Tool上で動かす</h3>
<pre><code class="language-text">npm run dev
</code></pre>
<p><a href="http://localhost:3979/devtools">http://localhost:3979/devtools</a> でチャット送ったり、発生したアクティビティを確認できる。ただし、メンションはできないっぽい？</p>
<h3>Teams上で動かす</h3>
<ul>
<li><a href="https://microsoft.github.io/teams-ai/typescript/getting-started/running-in-teams">https://microsoft.github.io/teams-ai/typescript/getting-started/running-in-teams</a></li>
</ul>
<p><a href="https://marketplace.visualstudio.com/items?itemName=TeamsDevApp.ms-teams-vscode-extension">Microsoft 365 Agents Toolkit</a> （VSCode拡張機能）をインストールしておく。</p>
<p>以下のコマンドで設定ファイルを追加する（環境変数追加されたり、マニフェストファイル追加されたり、vscodeでのデバッグ設定追加されたり）</p>
<pre><code class="language-text">teams config add atk.basic
</code></pre>
<p>VSCodeで M365 Agents Toolkit 拡張機能のパネルを開いて、”Accounts” セクションでM365アカウント、Azureアカウントでログインする。</p>
<p>次に、”Environment” セクションで “local” を選んでデバッグを開始する。「Debug（好きなブラウザ）」を選べばOK。</p>
<p>ブラウザでTeamsが立ち上がってくるが、無視してDesktopアプリのTeamsを起動。「アプリ > アプリを管理」から「アプリをアップロード」を選択（ブラウザではなぜか選択できない）</p>
<p>作成したTeamsアプリプロジェクトの <code>appPackage/build/appPackage.local.zip</code> を選択してアップロード。</p>
<p>後は、チャネルにインストールして使うだけ。オウム返しボットの場合ボット宛にメンションすれば、反応してくれる。</p>
<h2>メッセージに反応する</h2>
<ul>
<li><a href="https://microsoft.github.io/teams-ai/typescript/essentials/on-activity/">https://microsoft.github.io/teams-ai/typescript/essentials/on-activity/</a></li>
</ul>
<p>メッセージは Activity の一種で、Activity Router (<code>app.on()</code>) を使ってハンドリングする。</p>
<pre><code class="language-typescript">app.on("message", async ({ activity, send }) => {
	await send (`You said: ${activity.text}`);
});
</code></pre>
<p>他にもいろいろ Activity はある</p>
<ul>
<li><a href="https://microsoft.github.io/teams-ai/typescript/essentials/on-activity/activity-ref">https://microsoft.github.io/teams-ai/typescript/essentials/on-activity/activity-ref</a></li>
</ul>
<p>メッセージの場合、チャネルではbotに対するメンションが必要。↑のドキュメントでは <code>mention</code> がアクティビティであるとされているが、このSDKでは、"mention” をアクティビティとしてハンドリングできなかった。</p>
<h2>メンション判定</h2>
<p>botと1対1（DM）の時はメンションではないので、メンション判定できたほうが便利かもしれない。</p>
<p><code>activity.entities</code> にメッセージ内のメンション情報が入っている。こんな感じ？</p>
<pre><code class="language-typescript">const isMention = activity.entities &#x26;&#x26; activity.entities.some(entity => entity.type === 'mention');
</code></pre>
<p>チャネルかDMかの判定でもいいかも。</p>
<h2>DM/チャネル判定</h2>
<pre><code class="language-typescript">const isDM = activity.conversation.conversationType === 'personal';
</code></pre>
<p>型定義間違ってて補完には出てこないが、以下でチャネル判定できる</p>
<pre><code class="language-typescript">const isChannel = activity.conversation.conversationType === 'channel'
</code></pre>
<h2>DMにメッセージを送る</h2>
<p>例えば、何らかのアクティビティにトリガしてDMで通知を送るような場合</p>
<pre><code class="language-typescript">// メッセージを受け取ったら通知
app.on("message", async ({ activity, api }) => {

  const isChannel = activity.conversation.conversationType === "channel"
  if (!isChannel) {
    return;
  }

  const conversation = await api.conversations.create({
    tenantId: activity.conversation.tenantId,
    isGroup: false,
    bot: { id: activity.recipient.id },
    members: [activity.from]
  });

  await api.conversations.activities(conversation.id).create({
    type: 'message',
    text: `チャネルでのメッセージを受信しました: ${activity.text}`,
    from: activity.recipient,
    recipient: activity.from
  });
});
</code></pre>
<p>conversationを作って、そのidに対してアクティビティ（メッセージ）を作る。</p>
<h2>メッセージリンク</h2>
<pre><code class="language-typescript">const channelId = activity.channelData?.teamsChannelId || activity.conversation.id.split(';')[0];
const timestamp = activity.timestamp;
const conversationId = activity.converstation.id;
const parentMessageId = conversationId.split(';messageid=')[1];
const groupId = '多分テナント内で固定値？どれでもいいからメッセージリンクコピーして抜き出す';


const messageUrl = `https://teams.microsoft.com/l/message/${channelId}/${activity.id}?tenantId=${activity.conversation.tenantId}&#x26;groupId=${groupId}&#x26;parentMessageId=${parentMessageId}&#x26;createdTime=${timestamp}`;
</code></pre>
<h2>ユーザーのトークンでGraph APIを使う</h2>
<p>認証する必要あり。</p>
<ul>
<li><a href="https://microsoft.github.io/teams-ai/typescript/in-depth-guides/user-authentication/quickstart">https://microsoft.github.io/teams-ai/typescript/in-depth-guides/user-authentication/quickstart</a></li>
</ul>
<p>基本はドキュメント通りだが、デバッグの過程で、自動的にAzure側にリソースを作成されるので、対象サブスクリプションにリソースを作れる権限が必要。</p>
]]></description><link>https://blog.morimo.dev/posts/105-create-teams-app</link><guid isPermaLink="false">https://blog.morimo.dev/posts/105-create-teams-app</guid><pubDate>Fri, 20 Jun 2025 15:41:00 GMT</pubDate></item><item><title><![CDATA[段ボールカッター買ったー]]></title><description><![CDATA[<p>福岡、段ボールを捨てるのが面倒すぎるので、3年目にしてようやく電動段ボールカッターを買いました。スパスパ切れて気持ちいい！</p>
<p>福岡に引っ越す人は絶対に買おうね⚔️</p>
]]></description><link>https://blog.morimo.dev/posts/104-cardboard-cutter</link><guid isPermaLink="false">https://blog.morimo.dev/posts/104-cardboard-cutter</guid><pubDate>Sun, 01 Jun 2025 04:42:00 GMT</pubDate></item><item><title><![CDATA[2024-12-22]]></title><description><![CDATA[<p>超久し振りの更新。継続は難しい。</p>
<h2>やったこと</h2>
<ul>
<li>段ボール捨てた</li>
<li>React 19 の新機能キャッチアップ</li>
</ul>
<h2>段ボール捨てた</h2>
<p>前の賃貸では、24時間いつでも敷地内に段ボールを捨てられたが、福岡に引っ越してから、地域で決められた場所に決められた日時にしか捨てられなく、ためがちになってる。</p>
<p>福岡ってそういうもん？24時間いつでも捨てられる賃貸福岡にある？探し方が悪いだけなのかもしれない。</p>
<h2>React 19 の新機能キャッチアップ</h2>
<p>社内で共有することを目的にやっている。そのうちここで公開する。</p>
]]></description><link>https://blog.morimo.dev/posts/102-2024-12-22</link><guid isPermaLink="false">https://blog.morimo.dev/posts/102-2024-12-22</guid><pubDate>Sun, 22 Dec 2024 06:33:00 GMT</pubDate></item><item><title><![CDATA[React 19]]></title><description><![CDATA[<p>社内共有用。<a href="https://react.dev/blog/2024/12/05/react-19">React v19 – React</a> を少しずつ見ていく。</p>
<h2>Actions</h2>
<ul>
<li>非同期 transition を使う関数のことを “Action” と呼ぶ</li>
<li>ポイント
<ul>
<li>保留状態が管理される</li>
<li>楽観的更新がやりやすい</li>
<li>エラーハンドリング簡単
<ul>
<li>エラーが起きたら、Error Boundaries を表示したり、楽観的更新を元に戻したりできる（自動的に）</li>
</ul>
</li>
<li>フォームとも連携
<ul>
<li>formのaction propに関数を渡せるようになった。この関数は “Action” になる</li>
</ul>
</li>
</ul>
</li>
<li>この Action をベースにして、いくつかの hooks が追加されている</li>
</ul>
<h2>useActionState</h2>
<pre><code class="language-typescript">const [state, wrappedAction, isPending] = useActionState(action, initialState);
</code></pre>
<ul>
<li>引数に “Action” (<code>action</code>) を渡すと、実行用の ”ラップされた Action” を返す (<code>wrappedAction</code>)</li>
<li>この “ラップされた Action” を実行すると、”Action” の最後の実行結果を返す (<code>state</code>)</li>
<li>また、”Action” の保留状態を返す (<code>isPending</code>)</li>
</ul>
<p>stateは初回のレンダリングではinitialState, action が終わり次第、その戻り値に更新される</p>
<h2><code>&#x3C;form></code> Actions</h2>
<ul>
<li><code>&#x3C;form></code>, <code>&#x3C;input></code>, <code>&#x3C;button></code> の <code>action</code> , <code>formAction</code> prop に関数を渡せるようになった</li>
<li>prop に渡した関数は Action として扱われ、Action が完了すると、自動的に <code>&#x3C;form></code> がリセットされる
<ul>
<li>手動でリセットする口もある (<code>requestFormReset</code>)</li>
</ul>
</li>
</ul>
<pre><code class="language-typescript">&#x3C;form action={actionFunction}>
</code></pre>
<h2><code>useFormStatus</code></h2>
<ul>
<li>props なしで、Context を使わずに、親formの情報にアクセスできるhook</li>
<li>例えば、form で利用される汎用的な button コンポーネントの実装において、保留状態を取得して使う</li>
</ul>
<pre><code class="language-typescript">function DesignButton() {
  const { pending } = useFormStatus();
  return &#x3C;button type="submit" disabled={pending} />
}
</code></pre>
<ul>
<li>pending だけじゃなく、submit された data も取得できる</li>
<li>親formが無ければ null (pending の場合は false)</li>
</ul>
<p><a href="https://react.dev/reference/react-dom/hooks/useFormStatus">https://react.dev/reference/react-dom/hooks/useFormStatus</a></p>
<h2><code>useOptimistic</code></h2>
<ul>
<li>楽観的更新が簡単にできる hook</li>
</ul>
<h2><code>use</code></h2>
<ul>
<li>render 中にリソースを読み取るためのAPI</li>
<li>promise を読み込むと、use を使っているコンポーネントは promise が resolve (fulfilled) されるまで suspend される</li>
</ul>
<pre><code class="language-javascript">interface Todo {
    userId: number;
    id: number;
    title: string;
    completed: false;
}

async function fetchTodo(): Promise&#x3C;Todo> {
    const res = await fetch("https://jsonplaceholder.typicode.com/todos/1");
    return res.json();
}

export function Todo() {
    const todo = use(fetchTodo());
    return (
        &#x3C;p>
            {todo.title}
        &#x3C;/p>
    )
}

function App() {
  return (
    &#x3C;Suspense fallback={"loading..."}> 
      &#x3C;Todo />
    &#x3C;/Suspense>
  )
}
</code></pre>
<p>こんな感じで <code>useEffect</code> 無しでうまいことやれるようになるんかな、と思ったがそうではない。</p>
<p>👆のコードの場合、fallback が表示されっぱなしで Todo は表示されない。</p>
<p>ドキュメントには以下のように記述されている</p>
<blockquote>
<p>use はレンダー中に作成されたプロミスをサポートしない<br>
レンダー中に作成されたプロミスを use に渡そうとすると、React は警告を表示します。</p>
<p>修正するには、プロミスをキャッシュできるサスペンス対応のライブラリまたはフレームワークで作られたプロミスを渡す必要があります。将来的には、レンダー中にプロミスをキャッシュしやすくする機能を提供する予定です。</p>
</blockquote>
<p>「レンダ―中に作成されたプロミス」は、つまり <code>fetchTodo()</code> だが、「プロミスをキャッシュ」と言われてもよくわからない。</p>
<p>言っていることや、そもそも fallback が表示されっぱなしになる原因を理解するには、Suspense について理解する必要がある。</p>
<h3>そもそも <code>&#x3C;Suspense></code></h3>
<p><a href="https://react.dev/reference/react/Suspense">https://react.dev/reference/react/Suspense</a></p>
<p>Suspense による fallback と、その後のコンポーネントのレンダリングは以下の流れになる</p>
<ol>
<li>コンポーネントが render される過程で、Promise が throw されると、コンポーネントが「suspend」される</li>
<li><code>&#x3C;Suspense></code> は children（コンポーネント） が suspend すると、fallback をレンダーする</li>
<li>throw された Promise が resolve されると、Suspense の children を再レンダリングする</li>
</ol>
<p>先ほどの <code>use</code> に <code>fetchTodo()</code> を渡していたコードでは、この流れの 3 において、再度 <code>fetchTodo()</code> が実行されることになり、1~3 をループすることになってしまう（いつまで経ってもTODOは表示されない）</p>
<p>期待する動作（ <code>fetchTodo()</code> が完了したら、Todoコンポーネントに取得した Todo を表示する）を実現するには、3 (Promise が resolve され、Todoコンポーネントが再度レンダリングされるとき) において、use に渡される Promise が 1 で throw された Promise と同じである必要がある。</p>
<p>ドキュメントに書かれていた「プロミスをキャッシュ」とはこのことで、何らかの形で初回のPromiseをキャッシュしておいて、use に渡してあげる必要があるよ、と言うこと。</p>
<p>初回 (1) と同じ Promise を渡された use は resolve された Promise は throw しないので、再レンダリングされたとき、期待通りに Todo が表示される。</p>
<h3>どうやってキャッシュする？</h3>
<p>例えば、Tanstack Query の useQuery を使うと、キャッシュした Promise が得られる。</p>
<pre><code class="language-typescript">const { promise } = useQuery({
	queryKey: ["todos"],
	queryFn: fetchTodos,
	experimental_prefetchInRender: true, // このオプションを有効にすると promise がもらえる
});
</code></pre>
<ul>
<li><a href="https://speakerdeck.com/diggymo/reactnouse-tutehe-nan-6af6d25f-ac0d-4e61-b0db-c11b1737e906?slide=14">https://speakerdeck.com/diggymo/reactnouse-tutehe-nan-6af6d25f-ac0d-4e61-b0db-c11b1737e906?slide=14</a>
<ul>
<li>参考になりそう</li>
<li></li>
</ul>
</li>
</ul>
]]></description><link>https://blog.morimo.dev/posts/101-react-19</link><guid isPermaLink="false">https://blog.morimo.dev/posts/101-react-19</guid><pubDate>Thu, 19 Dec 2024 12:38:00 GMT</pubDate></item><item><title><![CDATA[自分が作成したツールをまとめたページを追加した]]></title><description><![CDATA[<p>自分が作成したツールが増えてきたので、それらをまとめた <a href="https://morimo.dev/tools">Tools</a> ページを追加した。</p>
<p><img src="https://r2.morimo.dev/tools_capture.png" alt="tools_capture.png"></p>
<p>そのうち、技術スタックやどういう目的で作成したツールなのかを詳細に書いたページを用意したい。</p>
]]></description><link>https://blog.morimo.dev/posts/99-tools-page</link><guid isPermaLink="false">https://blog.morimo.dev/posts/99-tools-page</guid><pubDate>Sat, 31 Aug 2024 04:44:00 GMT</pubDate></item><item><title><![CDATA[2024-06-09]]></title><description><![CDATA[<h2>やったこと</h2>
<ul>
<li>Cloudflare Workers でスクレイピング</li>
<li>アニメみた</li>
</ul>
<h2>Cloudflare Workers でスクレイピング</h2>
<p>個人用ダッシュボードのようなものを作りたい。表示するデータは、Cloudflare Workers を使って対象 Web ページをスクレイピングし、情報を D1 に貯め、Cloudflare Pages 上の Next.js アプリケーションから参照するような構成を考えていた。</p>
<p>しかし、Cloudflare Workers には <a href="https://developers.cloudflare.com/workers/platform/limits/#worker-limits">10ms の CPU time 制限</a>があり、Playwright や Puppeteer などを使ってヘッドレス Chrome を起動しスクレイピングするには不足していることがわかった。課金すれば <a href="https://blog.cloudflare.com/ja-jp/workers-now-even-more-unbound-ja-jp">Unbound モデル</a>の Workers を使うことで実現できたが、このために月5ドルは微妙だった。</p>
<p>そこで、スクレイピングは <a href="https://cloud.google.com/functions?hl=ja">Cloud Functions</a> で実行し、Cloudflare Workers はその Functions を叩いて結果をもらうだけにした。あくまでも CPU time の制限なので、Functions からのレスポンス待ちにかかる時間は対象外となる。だいぶ無駄ではあるが、今回の用途では速度は求めないので十分。これで安くスクレイピングが実現できた。</p>
<h2>アニメみた</h2>
<ul>
<li><a href="https://kanteiskill.com/">『転生貴族、鑑定スキルで成り上がる』公式ポータルサイト</a></li>
<li><a href="https://www.ten-sura.com/">【公式】「転生したらスライムだった件」ポータルサイト</a></li>
<li><a href="https://yorukura-anime.com/">オリジナルTVアニメーション「夜のクラゲは泳げない」公式サイト</a></li>
</ul>
<p>をみた。</p>
]]></description><link>https://blog.morimo.dev/posts/93-2024-06-09</link><guid isPermaLink="false">https://blog.morimo.dev/posts/93-2024-06-09</guid><pubDate>Sun, 09 Jun 2024 12:22:00 GMT</pubDate></item><item><title><![CDATA[2024-05-19]]></title><description><![CDATA[<h2>やったこと</h2>
<ul>
<li>Farm Together 2</li>
<li>お散歩</li>
</ul>
<h2><a href="https://store.steampowered.com/app/2418520/Farm_Together_2/?l=japanese">Farm Together 2</a></h2>
<p>4月15日にプレイし始めて、約40時間ほど遊んだ。こういうゲームをあまりやったことがなかったが、無限にタスクが湧いてきてやめ時を見つけられないくらいずっとプレイしてしまう。</p>
<p>効率良くプレイするために、3の倍数マスになるように整地する、お風呂に入って出たら収穫するから、収穫まで1時間かかる農作物を植える、など工夫してプレイするのが楽しい。</p>
]]></description><link>https://blog.morimo.dev/posts/92-2024-05-19</link><guid isPermaLink="false">https://blog.morimo.dev/posts/92-2024-05-19</guid><pubDate>Sun, 19 May 2024 05:11:00 GMT</pubDate></item><item><title><![CDATA[2024-05-09]]></title><description><![CDATA[<h2>やったこと</h2>
<ul>
<li>npm package の公開方法について調べた</li>
<li>shebang について調べた</li>
<li>崩壊：スターレイル を始めた</li>
</ul>
<h2>npm package の公開方法について調べた</h2>
<p>👇の手順に従うだけ。よく見かける <code>@hoge/package-name</code> の形式のパッケージは scoped package と呼ばれるらしい。</p>
<ul>
<li><a href="https://docs.npmjs.com/creating-and-publishing-scoped-public-packages">Creating and publishing scoped public packages | npm Docs</a></li>
</ul>
<p>公開前に作成したパッケージをインストールして正常に動作するか確認したい場合は、 <code>npm install</code> コマンドを使って対象パッケージディレクトリまでのフルパスを指定してインストールしてみればよいらしい。</p>
<p>ちなみに、<code>npm link</code> を使って試す方法もある。対象のパッケージディレクトリ内で <code>npm link</code> を実行。その後、動作確認用のディレクトリで <code>npm link &#x3C;pakcage-name></code> を実行すればOK。</p>
<ul>
<li><a href="https://docs.npmjs.com/cli/v10/commands/npm-link">npm-link | npm Docs</a></li>
</ul>
<h2>shebang について調べた</h2>
<p>node 向けの cli ツールに書かれている <code>#!/usr/bin/env node</code> が何か気になって調べた。shebang (シバン、シェバン) と呼ぶらしい。</p>
<ul>
<li><a href="https://ja.wikipedia.org/wiki/%E3%82%B7%E3%83%90%E3%83%B3_(Unix)">シバン (Unix) - Wikipedia</a></li>
</ul>
<p>対象スクリプトを読み込むインタプリタを指定する記述とのこと。なので、node 向け cli ツールは <code>#!/usr/bin/env node</code> と書く。</p>
<h2><strong>崩壊：スターレイル を</strong>始めた</h2>
<p>なんとなくソシャゲやりたい気分になり、始めてみた。実際始めたのは、5/8 で、かなり強いキャラの期間限定ガチャが終了した直後だったので、タイミング悪かったっぽい。とりあえずゆるくやっていく。</p>
]]></description><link>https://blog.morimo.dev/posts/91-2024-05-09</link><guid isPermaLink="false">https://blog.morimo.dev/posts/91-2024-05-09</guid><pubDate>Thu, 09 May 2024 14:16:00 GMT</pubDate></item><item><title><![CDATA[2024-04-29]]></title><description><![CDATA[<h2>やったこと</h2>
<ul>
<li>VSCode の Custom Labels を設定</li>
<li>Next.js on Cloudflare Pages + Cloudflare D1 お試し</li>
<li>Ordinary Labs USB A to C Cable (Orange) 買った</li>
<li>アニメ鑑賞</li>
</ul>
<h2>VSCode の Custom Labels を設定</h2>
<ul>
<li><a href="https://twitter.com/nextjs/status/1783508313113800930">https://twitter.com/nextjs/status/1783508313113800930</a></li>
</ul>
<p>このツイート（Post）を見て知った。<a href="https://code.visualstudio.com/updates/v1_88#_custom-labels-for-open-editors">2024年3月のVSCodeのアップデートで追加された</a>機能で、エディタのタブの表示をカスタマイズできる。Next.jsのようなワークスペース内に同名ファイルがたくさんある場合に便利。</p>
<p><code>.vscode/setting.json</code> の <code>"workbench.editor.customLabels.patterns"</code> で設定できる。glob pattern を使える。</p>
<pre><code class="language-json">{
  "workbench.editor.customLabels.patterns": {
    "**/app/**/page.tsx": "${dirname} - Page"
  }
}
</code></pre>
<p>とはいえ、もともと同名ファイルがタブに表示されるとき以下のようにディレクトリが表示され区別できるようになっているので、わざわざ設定しなくてもいいかもなと思った。</p>
<p><img src="https://r2.morimo.dev/20240429_vscode.png" alt="20240429_vscode.png"></p>
<h2>Next.js on Cloudflare Pages + Cloudflare D1 お試し</h2>
<ul>
<li><a href="https://developers.cloudflare.com/pages/framework-guides/nextjs/deploy-a-nextjs-site/">Full-stack deployment · Cloudflare Pages docs</a></li>
</ul>
<p>👆に従って Cloudflare Pages にデプロイ。D1 使うには、<a href="https://developers.cloudflare.com/workers/runtime-apis/bindings/#what-is-a-binding">Binding</a> する。</p>
<ul>
<li><a href="https://github.com/cloudflare/next-on-pages/tree/main/internal-packages/next-dev">next-on-pages/internal-packages/next-dev at main · cloudflare/next-on-pages</a></li>
</ul>
<p>Next.js の場合、<code>@cloudflare/next-on-pages</code> を使うことで、 <code>next dev</code> するだけでで binding された状態をローカルで動作させられる。</p>
<blockquote>
<p><strong>この最小のサンプルで、書き換えてから反映されるまで10秒以上かかる。</strong> それもロード中は 404 になり、ビルドが終わっても自動リフレッシュされたりとかはない。拷問か？</p>
<p><a href="https://zenn.dev/mizchi/scraps/fda07433250e82">https://zenn.dev/mizchi/scraps/fda07433250e82</a></p>
</blockquote>
<p>このスクラップを読んでいたので、しんどそうだと思っていたけれど、その後いい感じに整備されたぽい。</p>
<h2>Ordinary Labs USB A to C Cable (Orange) 買った</h2>
<ul>
<li><a href="https://ordinarylabs.com/products/ordinary-labs-usb-a-to-c-cable?variant=41085041410127">Ordinary Labs USB A to C Cable</a></li>
</ul>
<p>ぶっといケーブルかわいい。Orange、Black、Tiffany Blue の3色を買った。</p>
<h2>アニメ鑑賞</h2>
<ul>
<li>ダンジョン飯</li>
<li>無職転生</li>
</ul>
<p>を観た。無職転生が特に良かった…。早く続きが観たいヨ🥲</p>
<p>しばらくアニメを観られてなかったのでGW中にたくさん楽しむぞ。明日は、<a href="https://yorukura-anime.com/">夜のクラゲは泳げない</a> を観る。</p>
]]></description><link>https://blog.morimo.dev/posts/90-2024-04-29</link><guid isPermaLink="false">https://blog.morimo.dev/posts/90-2024-04-29</guid><pubDate>Mon, 29 Apr 2024 13:55:00 GMT</pubDate></item><item><title><![CDATA[2024-04-25]]></title><description><![CDATA[<h2>やったこと</h2>
<ul>
<li>「スタミナ源たれ」でカルビ丼</li>
</ul>
<h2>「スタミナ源たれ」でカルビ丼</h2>
<p>2月に買った<a href="https://store.grapht.tokyo/blogs/events/staminagentare-akamikarubi-collaboration">赤見かるびコラボのスタミナ源たれ</a>が届いたので、まずはカルビ丼にした。割と薄めの味で好きだった。色んな料理に使えそう。</p>
<p><img src="https://r2.morimo.dev/IMG_3600.jpeg" alt="IMG_3600.jpeg"></p>
<p>パッケージかわいいし、箱はかなり良い感じの質感だったので、取っておこうかな。</p>
]]></description><link>https://blog.morimo.dev/posts/89-2024-04-25</link><guid isPermaLink="false">https://blog.morimo.dev/posts/89-2024-04-25</guid><pubDate>Thu, 25 Apr 2024 12:38:00 GMT</pubDate></item><item><title><![CDATA[2024-04-24]]></title><description><![CDATA[<h2>やったこと</h2>
<ul>
<li>Cloudflare R2にブログの画像を配置</li>
<li>ダークモード時の文字色・背景色を調整</li>
</ul>
<h2>Cloudflare R2 にブログの画像を配置</h2>
<p><a href="https://www.cloudflare.com/ja-jp/developer-platform/r2/">Cloudflare R2</a> にこのブログの画像を配置することにした。</p>
<p>R2 に配置した画像にアクセスするには、Public access を有効にする。具体的には、対象バケットの設定からカスタムドメインを設定する。Cloudflare で管理しているドメインであれば設定できる。</p>
<p><img src="https://r2.morimo.dev/cloudflare_r2_custom_domain.png" alt="cloudflare_r2_custom_domain.png"></p>
<p>R2使い始めたはいいものの、 <a href="https://morimo.dev/">morimo.dev</a> になってから1枚も画像がありませんでしたとさ。</p>
<h2>ダークモード時の文字色・背景色を調整</h2>
<p>真っ黒に白文字は目が痛かったので、少し調整した。背景色、文字色共に Notion と同じにした。ロゴは真っ白がかわいいのでそのまま。</p>
<p>Before:</p>
<p><img src="https://r2.morimo.dev/20240424_before.png" alt="20240424_before.png"></p>
<p>After:</p>
<p><img src="https://r2.morimo.dev/20240424_after.png" alt="20240424_after.png"></p>
]]></description><link>https://blog.morimo.dev/posts/88-2024-04-24</link><guid isPermaLink="false">https://blog.morimo.dev/posts/88-2024-04-24</guid><pubDate>Wed, 24 Apr 2024 12:52:00 GMT</pubDate></item><item><title><![CDATA[2024-04-22]]></title><description><![CDATA[<h2>やったこと</h2>
<ul>
<li>かっぱえびせん 完熟かぼす味食べた</li>
<li>Cloudflare R2 調べた</li>
</ul>
<h2>かっぱえびせん 完熟かぼす味食べた</h2>
<p>セブンで新しく発売されていたので食べてみた。おいしかった。</p>
<p><a href="https://prtimes.jp/main/html/rd/p/000001305.000030525.html">収穫しきれなかった“完熟かぼす”を活用し産地を応援！ JA全農おおいた提供の大分県産かぼすを使用『ポテトチップス 完熟かぼす味』『かっぱえびせん 完熟かぼす味』 | カルビー株式会社のプレスリリース</a></p>
<h2>Cloudflare R2 調べた</h2>
<ul>
<li><a href="https://zenn.dev/razokulover/articles/144a98d27c658e#r2">Remix + Cloudflare Workers + D1 + KV + Queue + R2 + DOで簡単なアプリを作る</a></li>
</ul>
<p>👆の記事を読んで、このブログの画像もR2に保存する感じにしてみようかなと思った。</p>
<p>Workers 経由にせずとも、Public Buckets を有効にすれば直接バケットにアクセスできるらしい。</p>
<p><a href="https://developers.cloudflare.com/r2/buckets/public-buckets/">Public buckets · Cloudflare R2 docs</a></p>
<p>また土日に試そ❣</p>
]]></description><link>https://blog.morimo.dev/posts/87-2024-04-22</link><guid isPermaLink="false">https://blog.morimo.dev/posts/87-2024-04-22</guid><pubDate>Mon, 22 Apr 2024 13:49:00 GMT</pubDate></item><item><title><![CDATA[2024-04-21]]></title><description><![CDATA[<h2>やったこと</h2>
<ul>
<li>Cloudflareにドメイン移管</li>
</ul>
<h2>Cloudflareにドメイン移管</h2>
<p>以下の流れで移管できる</p>
<ol>
<li>CloudflareのWebsitesに移管対象ドメインを利用しているサイトを追加する</li>
<li>Cloudflareで移管手続きをする</li>
<li>移管を承認する</li>
</ol>
<h3>CloudflareのWebsitesに移管対象ドメインを利用しているサイトを追加する</h3>
<p>ダッシュボード（ホーム）で “Websites” メニューを選択し、”Add a site” からサイトを追加できる。</p>
<p>Cloudflareのネームサーバーを設定するよう案内されるので、現在利用しているレジストラで設定する。</p>
<h3>Cloudflareで移管申請をする</h3>
<p>ダッシュボード（ホーム）で “Domain Registration” > “Transfer Domains” を選択し、移管したいドメインを選択する。authorization code を求められるので、現在利用しているレジストラから取得して入力する。</p>
<p>あとは画面に従って確認を済ませれば、移管申請は完了する。</p>
<h3>移管を承認する</h3>
<p>現在利用しているレジストラから、移管申請を承認するよう連絡が来るので、承認する。しばらくすると、移管が完了し、Cloudflare上で完了したことを確認できる。</p>
]]></description><link>https://blog.morimo.dev/posts/86-2024-04-21</link><guid isPermaLink="false">https://blog.morimo.dev/posts/86-2024-04-21</guid><pubDate>Sun, 21 Apr 2024 06:31:00 GMT</pubDate></item><item><title><![CDATA[2024-04-20]]></title><description><![CDATA[<h2>今日の学び</h2>
<ul>
<li>可変フォント (variable fonts)</li>
</ul>
<h2>可変フォント (variable fonts)</h2>
<p>Next.js の <code>next/font/google</code> の使い方を調べてたところ、variable fonts なるものを使うことが<a href="https://nextjs.org/docs/app/building-your-application/optimizing/fonts#google-fonts">推奨されていた</a>。</p>
<p>MDNで調べてみたところ、以下の通り。</p>
<blockquote>
<p>可変フォント (Variable fonts) は幅、太さ、スタイルごとに個別のフォントファイルを用意するのではなく、書体のさまざまなバリエーションを 1 つのファイルに組み込むことができる OpenType フォント仕様の進化版です。CSS および単一の @font-face 参照を介して、特定のフォントファイルに含まれるすべてのバリエーションにアクセスできます。<br>
<a href="https://developer.mozilla.org/ja/docs/Web/CSS/CSS_fonts/Variable_fonts_guide">https://developer.mozilla.org/ja/docs/Web/CSS/CSS_fonts/Variable_fonts_guide</a></p>
</blockquote>
<p>つまり、可変フォントじゃないフォントは、文字の書体（太字、斜体など）毎にフォントファイルが分けられているが、variable fonts は1つのフォントファイルに様々な書体を含んでいるということ。そのため、ファイルサイズ自体が小さくなったり、読み込むファイル数を削減することができる。</p>
]]></description><link>https://blog.morimo.dev/posts/82-2024-04-20</link><guid isPermaLink="false">https://blog.morimo.dev/posts/82-2024-04-20</guid><pubDate>Sat, 20 Apr 2024 14:14:00 GMT</pubDate></item></channel></rss>