<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Oikon</title>
    <description>The latest articles on DEV Community by Oikon (@oikon).</description>
    <link>https://dev.to/oikon</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2232401%2Fbba816f2-c33f-4f10-ab1d-7eab6d2d6519.png</url>
      <title>DEV Community: Oikon</title>
      <link>https://dev.to/oikon</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/oikon"/>
    <language>en</language>
    <item>
      <title>Run `gh` Command in Claude Code on the Web</title>
      <dc:creator>Oikon</dc:creator>
      <pubDate>Mon, 12 Jan 2026 13:47:17 +0000</pubDate>
      <link>https://dev.to/oikon/run-gh-command-in-claude-code-on-the-web-2kp3</link>
      <guid>https://dev.to/oikon/run-gh-command-in-claude-code-on-the-web-2kp3</guid>
      <description>&lt;p&gt;I'm Oikon. I typically share Claude Code insights on &lt;a href="https://x.com/oikon48" rel="noopener noreferrer"&gt;X (Twitter)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Recently, Claude Code on the Web removed &lt;code&gt;gh&lt;/code&gt; from the &lt;code&gt;disallowed_tools&lt;/code&gt; list, making GitHub CLI available. In this article, I'll show you how to configure it. &lt;strong&gt;I've also published a setup package, so you can get started right away.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/oikon48" rel="noopener noreferrer"&gt;
        oikon48
      &lt;/a&gt; / &lt;a href="https://github.com/oikon48/gh-setup-hooks" rel="noopener noreferrer"&gt;
        gh-setup-hooks
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Enable `gh` command in Claude Code on the Web environment, just adding SessionStartHooks
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;gh-setup-hooks&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://www.npmjs.com/package/gh-setup-hooks" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/cbe5a02f438b219397414be26e3af13d5bd44a12366151bb1f5f9a7ee87a7d00/68747470733a2f2f62616467652e667572792e696f2f6a732f67682d73657475702d686f6f6b732e737667" alt="npm version"&gt;&lt;/a&gt;
&lt;a href="https://github.com/oikon48/gh-setup-hooks/LICENSE" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/fdf2982b9f5d7489dcf44570e714e3a15fce6253e0cc6b5aa61a075aac2ff71b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d79656c6c6f772e737667" alt="License: MIT"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Auto-install GitHub CLI on Claude Code on the Web. &lt;strong&gt;Just add one line to settings.json.&lt;/strong&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Setup&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;1. Add hook to settings.json&lt;/h3&gt;
&lt;/div&gt;
&lt;p&gt;Add to &lt;code&gt;.claude/settings.json&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight highlight-source-json notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;{
  &lt;span class="pl-ent"&gt;"hooks"&lt;/span&gt;: {
    &lt;span class="pl-ent"&gt;"SessionStart"&lt;/span&gt;: [
      {
        &lt;span class="pl-ent"&gt;"hooks"&lt;/span&gt;: [
          {
            &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;command&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
            &lt;span class="pl-ent"&gt;"command"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;bun x gh-setup-hooks&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
            &lt;span class="pl-ent"&gt;"timeout"&lt;/span&gt;: &lt;span class="pl-c1"&gt;120&lt;/span&gt;
          }
        ]
      }
    ]
  }
}&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;code&gt;npx -y gh-setup-hooks&lt;/code&gt; is also ok.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;2. Set up Claude Code on the Web&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;To use &lt;code&gt;gh&lt;/code&gt; commands (e.g., &lt;code&gt;gh pr create&lt;/code&gt;), you need to set &lt;code&gt;GH_TOKEN&lt;/code&gt; or &lt;code&gt;GITHUB_TOKEN&lt;/code&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://claude.ai/code" rel="nofollow noopener noreferrer"&gt;Claude Code on the Web&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Open &lt;strong&gt;Settings&lt;/strong&gt; → &lt;strong&gt;Custom Environment&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Add environment variable:
&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;GH_TOKEN&lt;/code&gt; or &lt;code&gt;GITHUB_TOKEN&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Value: Your &lt;a href="https://github.com/settings/tokens" rel="noopener noreferrer"&gt;GitHub Personal Access Token&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The token needs &lt;code&gt;repo&lt;/code&gt; scope for most operations.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Claude Code on the Web network should be &lt;strong&gt;Full&lt;/strong&gt; or &lt;strong&gt;Custom&lt;/strong&gt;. If using &lt;strong&gt;Custom&lt;/strong&gt;, you need to allow &lt;code&gt;release-assets.githubusercontent.com&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/oikon48/gh-setup-hooks/images/cloud-environment-settings.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Foikon48%2Fgh-setup-hooks%2Fimages%2Fcloud-environment-settings.png" width="400" alt="Cloud Environment Settings"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;How&lt;/h2&gt;…&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/oikon48/gh-setup-hooks" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;




&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Around December 17, 2025, &lt;code&gt;gh&lt;/code&gt; was removed from &lt;code&gt;disallowed_tools&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Configure &lt;code&gt;GITHUB_TOKEN&lt;/code&gt; in a custom environment&lt;/li&gt;
&lt;li&gt;Easy setup with &lt;code&gt;bun x gh-setup-hooks&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;CLAUDE_CODE_REMOTE&lt;/code&gt; to detect the "on the Web" environment&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt;&lt;br&gt;
The specifications in this article are based on Claude Code on the Web as of January 8, 2026. Some setup steps may become unnecessary if &lt;code&gt;gh&lt;/code&gt; command becomes installed by default in the future.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Quick Start
&lt;/h2&gt;

&lt;p&gt;Here's how to get &lt;code&gt;gh&lt;/code&gt; working in the shortest time possible.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Custom Environment Configuration
&lt;/h3&gt;

&lt;p&gt;Create a custom environment in Claude Code on the Web and configure the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Environment Variable&lt;/strong&gt;: &lt;code&gt;GITHUB_TOKEN=ghp_xxxx...&lt;/code&gt; (Personal Access Token issued from GitHub)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Network Access&lt;/strong&gt;: "Full" or "Custom" with &lt;code&gt;release-assets.githubusercontent.com&lt;/code&gt; allowed&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Hooks Configuration
&lt;/h3&gt;

&lt;p&gt;Add the following to your repository's &lt;code&gt;.claude/settings.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"SessionStart"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bun x gh-setup-hooks"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"timeout"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;120&lt;/span&gt;&lt;span class="w"&gt;
          &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;That's it! When you start a session in Claude Code on the Web, &lt;code&gt;gh&lt;/code&gt; will be automatically installed, enabling PR creation and issue management.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Warning:&lt;/strong&gt;&lt;br&gt;
Due to sandbox proxy configuration, you need to use the &lt;code&gt;-R owner/repo&lt;/code&gt; flag when using &lt;code&gt;gh&lt;/code&gt; commands. Claude Code often adds this automatically, but adding a note in CLAUDE.md makes things smoother.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2&gt;
  
  
  What is Claude Code on the Web?
&lt;/h2&gt;

&lt;p&gt;Claude Code on the Web is &lt;strong&gt;an environment where you can run Claude Code directly in your browser&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
      &lt;div class="c-embed__body flex items-center justify-between"&gt;
        &lt;a href="https://claude.ai/code" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;claude.ai&lt;/span&gt;
          

        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;





&lt;p&gt;The main appeal is that you can develop with just a browser, even without a PC at hand. It works by cloning GitHub repositories and running Claude Code in a sandboxed environment. For detailed specifications, please check out my previous article:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
        &lt;div class="c-embed__cover"&gt;
          &lt;a href="https://zenn.dev/oikon/articles/claude-code-web-sandbox" class="c-link align-middle" rel="noopener noreferrer"&gt;
            &lt;img alt="" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Fupload%2Fs--Ea8Y9bes--%2Fc_fit%252Cg_north_west%252Cl_text%3Anotosansjp-medium.otf_55%3AClaude%252520Code%252520on%252520the%252520Web%2525E3%252581%2525AE%2525E4%2525BB%252595%2525E6%2525A7%252598%2525E3%252582%252592%2525E5%2525BE%2525B9%2525E5%2525BA%252595%2525E8%2525A7%2525A3%2525E5%252589%252596%252Cw_1010%252Cx_90%252Cy_100%2Fg_south_west%252Cl_text%3Anotosansjp-medium.otf_37%3AOikon%252Cx_203%252Cy_121%2Fg_south_west%252Ch_90%252Cl_fetch%3AaHR0cHM6Ly9zdG9yYWdlLmdvb2dsZWFwaXMuY29tL3plbm4tdXNlci11cGxvYWQvYXZhdGFyLzYyMTkzODY4NjUuanBlZw%3D%3D%252Cr_max%252Cw_90%252Cx_87%252Cy_95%2Fv1627283836%2Fdefault%2Fog-base-w1200-v2.png%3F_a%3DBACAGSGT" height="auto" class="m-0"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="c-embed__body"&gt;
        &lt;h2 class="fs-xl lh-tight"&gt;
          &lt;a href="https://zenn.dev/oikon/articles/claude-code-web-sandbox" rel="noopener noreferrer" class="c-link"&gt;
            Claude Code on the Webの仕様を徹底解剖
          &lt;/a&gt;
        &lt;/h2&gt;
        &lt;div class="color-secondary fs-s flex items-center"&gt;
            &lt;img alt="favicon" class="c-embed__favicon m-0 mr-2 radius-0" src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fstatic.zenn.studio%2Fimages%2Flogo-transparent.png"&gt;
          zenn.dev
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;




&lt;p&gt;As a side note, by prefixing your Claude Code prompt with &lt;code&gt;&amp;amp;&lt;/code&gt;, you can send tasks from local Claude Code to Claude Code on the Web.&lt;/p&gt;

&lt;p&gt;

&lt;iframe class="tweet-embed" id="tweet-1996177293551747577-187" src="https://platform.twitter.com/embed/Tweet.html?id=1996177293551747577"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1996177293551747577-187');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1996177293551747577&amp;amp;theme=dark"
  }





&lt;/p&gt;

&lt;h2&gt;
  
  
  The Removal of &lt;code&gt;gh&lt;/code&gt; Command Restrictions
&lt;/h2&gt;

&lt;p&gt;Previously, the &lt;code&gt;gh&lt;/code&gt; command was explicitly blocked in Claude Code on the Web. The startup options included &lt;code&gt;--disallowed-tools Bash(gh:*)&lt;/code&gt;, and the system prompt contained this statement:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The GitHub CLI (&lt;code&gt;gh&lt;/code&gt;) is not available in this environment.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In other words, &lt;strong&gt;any GitHub CLI operations like creating PRs or managing issues were completely unavailable&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;However, around December 17, 2025, &lt;strong&gt;&lt;code&gt;gh&lt;/code&gt; had been removed from the &lt;code&gt;disallowed_tools&lt;/code&gt; list&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The diff in &lt;code&gt;data/startup.json&lt;/code&gt; shows that &lt;code&gt;"disallowed_tools": ["Bash(gh:*)"]&lt;/code&gt; has been removed. This means &lt;strong&gt;the gh command itself is no longer blocked&lt;/strong&gt;. However, since &lt;code&gt;gh&lt;/code&gt; isn't installed by default, you still can't use it out of the box.&lt;/p&gt;

&lt;h2&gt;
  
  
  How the Setup Works
&lt;/h2&gt;

&lt;p&gt;The gh-setup-hooks package uses sessionStartHooks to automatically install &lt;code&gt;gh&lt;/code&gt; at session start.&lt;/p&gt;

&lt;h3&gt;
  
  
  How It Works
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Hook fires at session start&lt;/li&gt;
&lt;li&gt;Checks if it's a "on the Web" environment using &lt;code&gt;CLAUDE_CODE_REMOTE&lt;/code&gt; environment variable&lt;/li&gt;
&lt;li&gt;Downloads and installs &lt;code&gt;gh&lt;/code&gt; only in the "on the Web" environment&lt;/li&gt;
&lt;li&gt;Writes PATH to &lt;code&gt;CLAUDE_ENV_FILE&lt;/code&gt; to enable it throughout the session&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  About the Environment Variables
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;&lt;code&gt;CLAUDE_CODE_REMOTE&lt;/code&gt;&lt;/strong&gt;: An environment variable set to &lt;code&gt;true&lt;/code&gt; only in the Claude Code on the Web environment. This allows the script to skip execution in local environments and run only in the "on the Web" environment.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CLAUDE_CODE_REMOTE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;"true"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;log &lt;span class="s2"&gt;"Not a remote session, skipping gh setup"&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;&lt;code&gt;CLAUDE_ENV_FILE&lt;/code&gt;&lt;/strong&gt;: An environment variable file path provided by Claude Code. Writing to this file persists PATH settings throughout the session.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CLAUDE_ENV_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"export PATH=&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="nv"&gt;$LOCAL_BIN&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;PATH&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CLAUDE_ENV_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    log &lt;span class="s2"&gt;"PATH persisted to CLAUDE_ENV_FILE"&lt;/span&gt;
&lt;span class="k"&gt;fi&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;
  Script Details (gh-setup.sh)
  &lt;p&gt;If you want to write your own script instead of using the package, here's a reference:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/bin/bash&lt;/span&gt;
&lt;span class="c"&gt;# SessionStart hook: GitHub CLI auto-installation for remote environments&lt;/span&gt;
&lt;span class="nb"&gt;set&lt;/span&gt; &lt;span class="nt"&gt;-e&lt;/span&gt;

&lt;span class="nv"&gt;LOG_PREFIX&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"[gh-setup]"&lt;/span&gt;
log&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LOG_PREFIX&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$1&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&amp;amp;2&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CLAUDE_CODE_REMOTE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;"true"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;log &lt;span class="s2"&gt;"Not a remote session, skipping gh setup"&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;span class="k"&gt;fi

&lt;/span&gt;log &lt;span class="s2"&gt;"Remote session detected, checking gh CLI..."&lt;/span&gt;

&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="nb"&gt;command&lt;/span&gt; &lt;span class="nt"&gt;-v&lt;/span&gt; gh &amp;amp;&amp;gt;/dev/null&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;log &lt;span class="s2"&gt;"gh CLI already available: &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;gh &lt;span class="nt"&gt;--version&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;span class="k"&gt;fi

&lt;/span&gt;&lt;span class="nv"&gt;LOCAL_BIN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$HOME&lt;/span&gt;&lt;span class="s2"&gt;/.local/bin"&lt;/span&gt;
&lt;span class="nb"&gt;mkdir&lt;/span&gt; &lt;span class="nt"&gt;-p&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LOCAL_BIN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-x&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LOCAL_BIN&lt;/span&gt;&lt;span class="s2"&gt;/gh"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;log &lt;span class="s2"&gt;"gh found in &lt;/span&gt;&lt;span class="nv"&gt;$LOCAL_BIN&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LOCAL_BIN&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CLAUDE_ENV_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"export PATH=&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="nv"&gt;$LOCAL_BIN&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;PATH&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CLAUDE_ENV_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
    &lt;span class="nb"&gt;exit &lt;/span&gt;0
&lt;span class="k"&gt;fi

&lt;/span&gt;log &lt;span class="s2"&gt;"Installing gh CLI to &lt;/span&gt;&lt;span class="nv"&gt;$LOCAL_BIN&lt;/span&gt;&lt;span class="s2"&gt;..."&lt;/span&gt;

&lt;span class="nv"&gt;TEMP_DIR&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;mktemp&lt;/span&gt; &lt;span class="nt"&gt;-d&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;trap&lt;/span&gt; &lt;span class="s2"&gt;"rm -rf &lt;/span&gt;&lt;span class="nv"&gt;$TEMP_DIR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; EXIT

&lt;span class="nv"&gt;ARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;uname&lt;/span&gt; &lt;span class="nt"&gt;-m&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$ARCH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="k"&gt;in
    &lt;/span&gt;x86_64&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;GH_ARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"amd64"&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;
    aarch64|arm64&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nv"&gt;GH_ARCH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"arm64"&lt;/span&gt; &lt;span class="p"&gt;;;&lt;/span&gt;
    &lt;span class="k"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; log &lt;span class="s2"&gt;"Unsupported architecture: &lt;/span&gt;&lt;span class="nv"&gt;$ARCH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;0 &lt;span class="p"&gt;;;&lt;/span&gt;
&lt;span class="k"&gt;esac&lt;/span&gt;

&lt;span class="nv"&gt;GH_VERSION&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"2.62.0"&lt;/span&gt;
&lt;span class="nv"&gt;GH_URL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"https://github.com/cli/cli/releases/download/v&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GH_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/gh_&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GH_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_linux_&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GH_ARCH&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.tar.gz"&lt;/span&gt;

curl &lt;span class="nt"&gt;-sL&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$GH_URL&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="nt"&gt;-o&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TEMP_DIR&lt;/span&gt;&lt;span class="s2"&gt;/gh.tar.gz"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; log &lt;span class="s2"&gt;"Failed to download"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;0&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;tar&lt;/span&gt; &lt;span class="nt"&gt;-xzf&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TEMP_DIR&lt;/span&gt;&lt;span class="s2"&gt;/gh.tar.gz"&lt;/span&gt; &lt;span class="nt"&gt;-C&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TEMP_DIR&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; log &lt;span class="s2"&gt;"Failed to extract"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;0&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="nb"&gt;mv&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$TEMP_DIR&lt;/span&gt;&lt;span class="s2"&gt;/gh_&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GH_VERSION&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;_linux_&lt;/span&gt;&lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;GH_ARCH&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/bin/gh"&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LOCAL_BIN&lt;/span&gt;&lt;span class="s2"&gt;/gh"&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt; log &lt;span class="s2"&gt;"Failed to install"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nb"&gt;exit &lt;/span&gt;0&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;chmod&lt;/span&gt; +x &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LOCAL_BIN&lt;/span&gt;&lt;span class="s2"&gt;/gh"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;PATH&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$LOCAL_BIN&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="nv"&gt;$PATH&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-n&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CLAUDE_ENV_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"export PATH=&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="nv"&gt;$LOCAL_BIN&lt;/span&gt;&lt;span class="s2"&gt;:&lt;/span&gt;&lt;span class="se"&gt;\$&lt;/span&gt;&lt;span class="s2"&gt;PATH&lt;/span&gt;&lt;span class="se"&gt;\"&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$CLAUDE_ENV_FILE&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;

log &lt;span class="s2"&gt;"gh CLI installed successfully: &lt;/span&gt;&lt;span class="si"&gt;$(&lt;/span&gt;&lt;span class="nv"&gt;$LOCAL_BIN&lt;/span&gt;/gh &lt;span class="nt"&gt;--version&lt;/span&gt; | &lt;span class="nb"&gt;head&lt;/span&gt; &lt;span class="nt"&gt;-1&lt;/span&gt;&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;/p&gt;
&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;With &lt;code&gt;gh&lt;/code&gt; now available, you can read issues and execute tasks, or create PRs directly in Claude Code on the Web. The &lt;code&gt;CLAUDE_CODE_REMOTE&lt;/code&gt; variable can also be useful for other remote-only workflows.&lt;/p&gt;



&lt;p&gt;If you found this article valuable, follow the author on &lt;a href="https://x.com/oikon48" rel="noopener noreferrer"&gt;X (@oikon48)&lt;/a&gt; for ongoing Claude Code insights and updates.&lt;/p&gt;


&lt;h2&gt;
  
  
  References
&lt;/h2&gt;
&lt;h3&gt;
  
  
  GitHub
&lt;/h3&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/oikon48" rel="noopener noreferrer"&gt;
        oikon48
      &lt;/a&gt; / &lt;a href="https://github.com/oikon48/gh-setup-hooks" rel="noopener noreferrer"&gt;
        gh-setup-hooks
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Enable `gh` command in Claude Code on the Web environment, just adding SessionStartHooks
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;gh-setup-hooks&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="https://www.npmjs.com/package/gh-setup-hooks" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/cbe5a02f438b219397414be26e3af13d5bd44a12366151bb1f5f9a7ee87a7d00/68747470733a2f2f62616467652e667572792e696f2f6a732f67682d73657475702d686f6f6b732e737667" alt="npm version"&gt;&lt;/a&gt;
&lt;a href="https://github.com/oikon48/gh-setup-hooks/LICENSE" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/fdf2982b9f5d7489dcf44570e714e3a15fce6253e0cc6b5aa61a075aac2ff71b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d79656c6c6f772e737667" alt="License: MIT"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Auto-install GitHub CLI on Claude Code on the Web. &lt;strong&gt;Just add one line to settings.json.&lt;/strong&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Setup&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;1. Add hook to settings.json&lt;/h3&gt;
&lt;/div&gt;
&lt;p&gt;Add to &lt;code&gt;.claude/settings.json&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight highlight-source-json notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;{
  &lt;span class="pl-ent"&gt;"hooks"&lt;/span&gt;: {
    &lt;span class="pl-ent"&gt;"SessionStart"&lt;/span&gt;: [
      {
        &lt;span class="pl-ent"&gt;"hooks"&lt;/span&gt;: [
          {
            &lt;span class="pl-ent"&gt;"type"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;command&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
            &lt;span class="pl-ent"&gt;"command"&lt;/span&gt;: &lt;span class="pl-s"&gt;&lt;span class="pl-pds"&gt;"&lt;/span&gt;bun x gh-setup-hooks&lt;span class="pl-pds"&gt;"&lt;/span&gt;&lt;/span&gt;,
            &lt;span class="pl-ent"&gt;"timeout"&lt;/span&gt;: &lt;span class="pl-c1"&gt;120&lt;/span&gt;
          }
        ]
      }
    ]
  }
}&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;code&gt;npx -y gh-setup-hooks&lt;/code&gt; is also ok.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;2. Set up Claude Code on the Web&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;To use &lt;code&gt;gh&lt;/code&gt; commands (e.g., &lt;code&gt;gh pr create&lt;/code&gt;), you need to set &lt;code&gt;GH_TOKEN&lt;/code&gt; or &lt;code&gt;GITHUB_TOKEN&lt;/code&gt;:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Go to &lt;a href="https://claude.ai/code" rel="nofollow noopener noreferrer"&gt;Claude Code on the Web&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Open &lt;strong&gt;Settings&lt;/strong&gt; → &lt;strong&gt;Custom Environment&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Add environment variable:
&lt;ul&gt;
&lt;li&gt;Name: &lt;code&gt;GH_TOKEN&lt;/code&gt; or &lt;code&gt;GITHUB_TOKEN&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Value: Your &lt;a href="https://github.com/settings/tokens" rel="noopener noreferrer"&gt;GitHub Personal Access Token&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: The token needs &lt;code&gt;repo&lt;/code&gt; scope for most operations.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Claude Code on the Web network should be &lt;strong&gt;Full&lt;/strong&gt; or &lt;strong&gt;Custom&lt;/strong&gt;. If using &lt;strong&gt;Custom&lt;/strong&gt;, you need to allow &lt;code&gt;release-assets.githubusercontent.com&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/oikon48/gh-setup-hooks/images/cloud-environment-settings.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Foikon48%2Fgh-setup-hooks%2Fimages%2Fcloud-environment-settings.png" width="400" alt="Cloud Environment Settings"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;How&lt;/h2&gt;…&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/oikon48/gh-setup-hooks" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;




&lt;h3&gt;
  
  
  Documentation
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://docs.claude.com/en/docs/claude-code/claude-code-on-the-web" rel="noopener noreferrer"&gt;Claude Code on the Web - Official Documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.claude.com/en/docs/claude-code/hooks" rel="noopener noreferrer"&gt;Claude Code Hooks - Official Documentation&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens" rel="noopener noreferrer"&gt;Managing Personal Access Tokens - GitHub Docs&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Related Articles
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://zenn.dev/oikon/articles/claude-code-web-sandbox" rel="noopener noreferrer"&gt;Claude Code on the Web Sandbox Specifications (Japanese)&lt;/a&gt;&lt;/p&gt;

</description>
      <category>claudecode</category>
      <category>claude</category>
      <category>ai</category>
      <category>coding</category>
    </item>
    <item>
      <title>Reflections of Claude Code from CHANGELOG</title>
      <dc:creator>Oikon</dc:creator>
      <pubDate>Tue, 30 Dec 2025 14:53:24 +0000</pubDate>
      <link>https://dev.to/oikon/reflections-of-claude-code-from-changelog-833</link>
      <guid>https://dev.to/oikon/reflections-of-claude-code-from-changelog-833</guid>
      <description>&lt;p&gt;I'm Oikon. I typically share Claude Code insights on &lt;a href="https://x.com/oikon48" rel="noopener noreferrer"&gt;X (Twitter)&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As this eventful year of 2025 draws to a close, I wanted to reflect on Claude Code. For me personally, 2025 was the year AI agents took a massive leap forward. More specifically, &lt;strong&gt;it was the year of Claude Code&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;a href="https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md" rel="noopener noreferrer"&gt;Claude Code CHANGELOG&lt;/a&gt; has been updated 176 times total. I have verified and tested every release since at least v1.0.x.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Version Series&lt;/th&gt;
&lt;th&gt;Release Count (as of 2025/12/30)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;v0.2.x&lt;/td&gt;
&lt;td&gt;37&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;v1.0.x&lt;/td&gt;
&lt;td&gt;82&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;v2.0.x&lt;/td&gt;
&lt;td&gt;57&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Total&lt;/td&gt;
&lt;td&gt;176&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Having worked closely with Claude Code throughout the year, I want to organize my thoughts on what I have learned. Please note that these are my personal observations.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Here are the key takeaways from a year of tracking Claude Code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude Code shipped 176 updates in 2025, demonstrating rapid iteration from beta to v2.0&lt;/li&gt;
&lt;li&gt;Context engineering emerged as the unifying theme across major features&lt;/li&gt;
&lt;li&gt;Key milestones: CLAUDE.md memory files, Plan mode, Subagents, /context command, Skills, and Opus 4.5&lt;/li&gt;
&lt;li&gt;Claude Code's strength lies in its harness design, optimized specifically for Claude models&lt;/li&gt;
&lt;li&gt;Challenges remain: 200k context window (vs competitors' 400k-1M), compaction quality, and knowledge cutoff&lt;/li&gt;
&lt;li&gt;2026 outlook: Long-running tasks, Swarming capabilities, and enhanced external tool integration&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Shock of First Contact
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Before Claude Code
&lt;/h3&gt;

&lt;p&gt;I first touched Claude Code in March 2025, not February when the beta released.&lt;/p&gt;

&lt;p&gt;At the time, I was using GitHub Copilot and Cursor while asking ChatGPT and Claude's web version about code, then copy-pasting the good bits and tweaking them locally. Looking back, my development workflow has transformed dramatically over the past year.&lt;/p&gt;

&lt;p&gt;Even then, Claude's web version had GitHub integration and could read codebases to answer questions. I personally felt Claude 3.7's coding quality was superior to other AI models at the time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Meeting Claude Code
&lt;/h3&gt;

&lt;p&gt;In March 2025, I discovered a product called Claude Code. I cannot find my posts from that period since I was not active on X yet, but I remember seeing someone demo it on social media. While IDE-based tools like Cursor and Windsurf were getting attention, the CLI approach caught my eye.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;I was deeply impressed when I first tried Claude Code.&lt;/strong&gt; Previous AI tools worked alongside you while coding, but even the early Claude Code could autonomously code and create multiple components on its own.&lt;/p&gt;

&lt;p&gt;Watching an AI agent explore the codebase independently, gather necessary information, and implement features made me realize coding was about to change fundamentally.&lt;/p&gt;

&lt;p&gt;From April onward, I continued using Claude Code with pay-as-you-go API billing while getting comfortable with CLI-based coding. Around that time, I started posting on X, praising Claude Code and expressing interest in trying Codex CLI. As a side note, the Codex CLI back then was honestly not very usable, and many people today do not even know it existed. When GPT-5 arrived, Codex CLI transformed dramatically, following a similar trajectory to Claude Code's official release.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Claude Code is really good, so I want to try Codex too, but the heavy pay-per-use billing makes it hard to use comfortably."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;

&lt;iframe class="tweet-embed" id="tweet-1913180659004350849-956" src="https://platform.twitter.com/embed/Tweet.html?id=1913180659004350849"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1913180659004350849-956');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1913180659004350849&amp;amp;theme=dark"
  }





&lt;/p&gt;

&lt;p&gt;On April 9, the Claude Max plan was announced. &lt;strong&gt;On May 1, Claude Code became available at a flat rate through the Max plan.&lt;/strong&gt; This did not get much attention at the time, but it laid the groundwork for Claude Code's wider adoption.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://claude.com/blog/max-plan" rel="noopener noreferrer"&gt;Claude Max Plan Announcement&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A few days after that announcement, I subscribed to the Max 5x plan at $100/month. Until then, I had never spent more than $20 on AI tools, so this was a significant shift. Now I use the 20x plan at $200/month, which shows how much things have changed.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Using Claude Code through Claude Desktop + MCP without API charges is nice, but it still can't match the speed of developing directly with Claude Code. I keep hitting Desktop's chat limits anyway. Better to stop being stingy and just subscribe to the Max plan. +12,000 yen monthly..."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;

&lt;iframe class="tweet-embed" id="tweet-1919078662323745066-937" src="https://platform.twitter.com/embed/Tweet.html?id=1919078662323745066"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1919078662323745066-937');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1919078662323745066&amp;amp;theme=dark"
  }





&lt;/p&gt;

&lt;h2&gt;
  
  
  The Official Launch
&lt;/h2&gt;

&lt;p&gt;On May 25, 2025, Anthropic announced Claude 4. I wrote a Zenn article about that moment, which you can read here:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://zenn.dev/oikon/articles/adac12ea9e839b" rel="noopener noreferrer"&gt;My Zenn article about Claude 4 release&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The major changes for Claude Code at this point were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Claude 4 (Opus/Sonnet) performance was excellent&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The Max flat-rate plan gained recognition&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Claude Code had already shown autonomous capabilities, but with Claude 3.7, the model's performance was not quite sufficient to fully leverage the harness's power. &lt;strong&gt;Claude 4's arrival improved how Claude handled tools&lt;/strong&gt;, reaching a level where it could truly excel.&lt;/p&gt;

&lt;p&gt;The Max plan's recognition mattered too. Traditional AI coding involved cautious usage due to pay-per-use API billing. With flat-rate Claude Code access, the AI coding mindset shifted, enabling experimentation and multiple implementation attempts. This flat-rate model has been adopted across the industry, including Codex, Gemini, and some Cursor plans.&lt;/p&gt;

&lt;h2&gt;
  
  
  Tracking the CHANGELOG
&lt;/h2&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/anthropics" rel="noopener noreferrer"&gt;
        anthropics
      &lt;/a&gt; / &lt;a href="https://github.com/anthropics/claude-code" rel="noopener noreferrer"&gt;
        claude-code
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Claude Code&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/92c4b317cff472ae3476218ac6a59a4e1e2071b074166d0a003953d6a4408ff1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4e6f64652e6a732d31382532422d627269676874677265656e3f7374796c653d666c61742d737175617265"&gt;&lt;img src="https://camo.githubusercontent.com/92c4b317cff472ae3476218ac6a59a4e1e2071b074166d0a003953d6a4408ff1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4e6f64652e6a732d31382532422d627269676874677265656e3f7374796c653d666c61742d737175617265" alt=""&gt;&lt;/a&gt; &lt;a href="https://www.npmjs.com/package/@anthropic-ai/claude-code" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/54fc0e51d112658ac0d5ef0a25e03c9ebcbf5bf0068b35d818cdc18825f97bf8/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f40616e7468726f7069632d61692f636c617564652d636f64652e7376673f7374796c653d666c61742d737175617265" alt="npm"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows -- all through natural language commands. Use it in your terminal, IDE, or tag &lt;a class="mentioned-user" href="https://dev.to/claude"&gt;@claude&lt;/a&gt; on Github.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Learn more in the &lt;a href="https://code.claude.com/docs/en/overview" rel="nofollow noopener noreferrer"&gt;official documentation&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/anthropics/claude-code/./demo.gif"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fanthropics%2Fclaude-code%2F.%2Fdemo.gif"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Get started&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="markdown-alert markdown-alert-note"&gt;
&lt;p class="markdown-alert-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Installation via npm is deprecated. Use one of the recommended methods below.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;For more installation options, uninstall steps, and troubleshooting, see the &lt;a href="https://code.claude.com/docs/en/setup" rel="nofollow noopener noreferrer"&gt;setup documentation&lt;/a&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Install Claude Code:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MacOS/Linux (Recommended):&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;curl -fsSL https://claude.ai/install.sh &lt;span class="pl-k"&gt;|&lt;/span&gt; bash&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Homebrew (MacOS/Linux):&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;brew install --cask claude-code&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Windows (Recommended):&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight highlight-source-powershell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;irm https:&lt;span class="pl-k"&gt;//&lt;/span&gt;claude.ai&lt;span class="pl-k"&gt;/&lt;/span&gt;install.ps1 &lt;span class="pl-k"&gt;|&lt;/span&gt; iex&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;WinGet (Windows):&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight highlight-source-powershell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;winget install Anthropic.ClaudeCode&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;NPM (Deprecated):&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm install -g @anthropic-ai/claude-code&lt;/pre&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Navigate to your project directory and run &lt;code&gt;claude&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Plugins&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;This repository includes several Claude Code plugins that extend functionality with custom commands and agents. See the &lt;a href="https://github.com/anthropics/claude-code/./plugins/README.md" rel="noopener noreferrer"&gt;plugins&lt;/a&gt;…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/anthropics/claude-code" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;




&lt;p&gt;With Claude 4's release, Claude Code itself received its first major update to v1.0.x. As of December 2025, we are on v2.0.x (v2.0.74 at the time of writing).&lt;/p&gt;

&lt;p&gt;I cannot cover all 176 updates, so I will highlight the changes from v1.0.x onward that I found most impactful.&lt;/p&gt;

&lt;p&gt;To summarize upfront: &lt;strong&gt;many features are strongly tied to context engineering&lt;/strong&gt;, suggesting that understanding context engineering is essential right now.&lt;/p&gt;

&lt;h3&gt;
  
  
  Claude Code v1.0.x Era
&lt;/h3&gt;

&lt;h4&gt;
  
  
  CLAUDE.md (Memory Files)
&lt;/h4&gt;

&lt;p&gt;CLAUDE.md existed since v0.2.x, but with the v1.0.x release, discussions about &lt;strong&gt;what should go in CLAUDE.md&lt;/strong&gt; intensified. While Cursor Rules existed before, CLAUDE.md became more critical for Claude Code's autonomous implementation.&lt;/p&gt;

&lt;p&gt;As the term &lt;strong&gt;context engineering&lt;/strong&gt; spread and the importance of controlling AI agent context windows gained attention, CLAUDE.md's significance grew further.&lt;/p&gt;

&lt;p&gt;In August, Codex CLI proposed &lt;a href="https://agents.md/" rel="noopener noreferrer"&gt;AGENTS.md&lt;/a&gt;, attempting to unify project memory across AI tools. This move reflects the impact CLAUDE.md had on AI coding.&lt;/p&gt;

&lt;p&gt;Incidentally, Claude Code does not support AGENTS.md. This has been discussed among users in a GitHub Issue:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/anthropics/claude-code/issues/6235" rel="noopener noreferrer"&gt;GitHub Issue: AGENTS.md Support&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Personally, I do not think Anthropic will support AGENTS.md. Here is why:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Adopting OpenAI's standard poses competitive challenges&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Workarounds already exist in Claude Code&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A universal project memory for all harnesses and models is difficult&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Anthropic has created industry standards like MCP and recently Agent Skills, but they seem cautious about adopting others' specifications.&lt;/p&gt;

&lt;p&gt;As the GitHub Issue shows, workarounds like &lt;code&gt;@&lt;/code&gt; imports and symbolic links exist. I covered these in my advent calendar article under Day 5:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://medium.com/generative-ai/24-claude-code-tips-claude-code-advent-calendar-7c666aee0428?sk=9d70e1cb755cb97ecc01179ad4aed39e" rel="noopener noreferrer"&gt;24 Claude Code Tips - Claude Code Advent Calendar&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Finally, I personally find &lt;strong&gt;the idea that one AGENTS.md can serve all AI tools somewhat challenging&lt;/strong&gt;. AI tools combine models and harnesses, and fully leveraging each requires tool-specific project memory. Unlike MCP, AGENTS.md is natural language Markdown, not really a protocol.&lt;/p&gt;

&lt;p&gt;This may be why Anthropic is not eager to consolidate around AGENTS.md.&lt;/p&gt;

&lt;h4&gt;
  
  
  Plan Mode
&lt;/h4&gt;

&lt;p&gt;Plan mode was silently added around v1.0.18 on June 12. You can switch to it with &lt;code&gt;Shift + Tab&lt;/code&gt; or set it as the default via &lt;code&gt;/config&lt;/code&gt;. If I recall correctly, Cline had introduced Plan mode around April, before Claude Code.&lt;/p&gt;

&lt;p&gt;At the time, I was caught up in Vibe Coding and foolishly running &lt;code&gt;--dangerously-skip-permission&lt;/code&gt;, so I failed to immediately grasp its value. But as I used Claude Code longer, I came to appreciate Plan mode's utility.&lt;/p&gt;

&lt;p&gt;Plan mode matters because it &lt;strong&gt;clarifies the AI agent's execution steps beforehand&lt;/strong&gt;. Many AI coding failures stem from unclear execution sequences, where the agent does not follow the intended implementation path.&lt;/p&gt;

&lt;p&gt;Plan mode's value extends to &lt;strong&gt;improving downstream bottlenecks&lt;/strong&gt;. By clarifying specifications upfront, the agent follows them more closely, reducing deviation from expected output. This indirectly reduces review bottlenecks that have become apparent in AI coding. Like Shift Left Testing, eliminating rework early benefits later stages.&lt;/p&gt;

&lt;p&gt;When I asked Boris Cherny, a Claude Code developer, about Plan mode's importance, he confirmed it. He said he starts in Plan mode almost every time.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The single biggest tip is: almost always start in plan mode. Once you align on a detailed plan, Opus 4.5 gets it right pretty much every time."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;

&lt;iframe class="tweet-embed" id="tweet-2004711107018342430-748" src="https://platform.twitter.com/embed/Tweet.html?id=2004711107018342430"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-2004711107018342430-748');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=2004711107018342430&amp;amp;theme=dark"
  }





&lt;/p&gt;

&lt;p&gt;The latest Claude Code now creates Plan documents in &lt;code&gt;~/.claude/plans/&lt;/code&gt;, moving toward something like Spec Driven Development (SDD). I covered this in &lt;a href="https://medium.com/generative-ai/24-claude-code-tips-claude-code-advent-calendar-7c666aee0428?sk=9d70e1cb755cb97ecc01179ad4aed39e" rel="noopener noreferrer"&gt;Advent Calendar Day 17&lt;/a&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Subagents
&lt;/h4&gt;

&lt;p&gt;Subagents have existed since early Claude Code, operating as the &lt;code&gt;Task&lt;/code&gt; tool. I wrote about them in this article:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://zenn.dev/oikon/articles/82c9a52dc45810" rel="noopener noreferrer"&gt;My article on Subagents&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Starting with v1.0.60, the &lt;code&gt;/agents&lt;/code&gt; command enabled custom Subagents.&lt;/p&gt;

&lt;p&gt;Subagents have these characteristics:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Parallel execution capability&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Role specialization&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Independent context windows&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The independent context window is particularly important from a context engineering perspective. Current Claude Code context windows are limited, and heavy &lt;code&gt;WebSearch&lt;/code&gt; or &lt;code&gt;Read&lt;/code&gt; operations quickly fill them.&lt;/p&gt;

&lt;p&gt;Subagents help by &lt;strong&gt;keeping extraneous information out of the parent context window&lt;/strong&gt;, offloading it to their own. Given current context engineering constraints, having this escape valve matters.&lt;/p&gt;

&lt;p&gt;As AI agent orchestration advances, Subagents' parallel execution capability will become increasingly important.&lt;/p&gt;

&lt;h4&gt;
  
  
  /context
&lt;/h4&gt;

&lt;p&gt;The &lt;code&gt;/context&lt;/code&gt; command was added in v1.0.86 on August 20. Its value lies in visualizing context.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr8wly6qyphoti5ww4601.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr8wly6qyphoti5ww4601.png" alt="/context"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;While context engineering as a concept had spread, many people understood it abstractly without truly grasping it.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;/context&lt;/code&gt; displays:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;System prompt&lt;/li&gt;
&lt;li&gt;System tools&lt;/li&gt;
&lt;li&gt;MCP tools&lt;/li&gt;
&lt;li&gt;Custom agents&lt;/li&gt;
&lt;li&gt;Memory files&lt;/li&gt;
&lt;li&gt;Messages&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This makes it immediately clear &lt;strong&gt;how much context window is occupied and how much remains&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;/context&lt;/code&gt; command helped many users become aware of context windows and understand context engineering's importance. A common example now discussed: MCP tools consume significant space, so removing unnecessary ones helps. This conversation was impossible before &lt;code&gt;/context&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;By illuminating the abstract concept of context engineering and making it tangible, the &lt;code&gt;/context&lt;/code&gt; command made a major contribution.&lt;/p&gt;

&lt;h3&gt;
  
  
  Claude Code v2.0.x Era
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Opus 4.5
&lt;/h4&gt;

&lt;p&gt;The v2.0.x era's most significant event was &lt;strong&gt;Claude Opus 4.5's release on November 24&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;At the time, many were migrating from Claude Code to Codex CLI. Reasons included rumors of Claude Code degradation and GPT-5.1 Codex's excellence. I was still primarily on Claude Code with Codex CLI as backup, though Codex had a meaningful share of my tasks.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.anthropic.com/news/claude-opus-4-5" rel="noopener noreferrer"&gt;Claude Opus 4.5 Announcement&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When Opus 4.5 became available in Claude Code starting v2.0.51, users gradually returned. I say "gradually" because at this stage, AI models had become difficult to distinguish through simple implementation tasks. Many felt they needed hours or days of use to understand the differences. Codex CLI had also evolved into an excellent tool, and Cursor had established its position with Composer-1.&lt;/p&gt;

&lt;p&gt;Using it myself, I found Claude Opus 4.5 handled Claude Code's tool specifications well, with satisfactory implementation speed. The affinity between Opus 4.5 and the Claude Code harness felt higher than previous Claude Opus 4.1 or Sonnet 4.5. &lt;strong&gt;Claude Opus 4.5 undeniably elevated Claude Code's standing and pushed AI coding history forward.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As an aside, measuring AI model performance has become personally challenging. Simple tasks yield high-quality output from any AI tool now.&lt;/p&gt;

&lt;p&gt;SWE-Bench is often cited, but it increasingly feels like marketing performance. Real confidence comes only from hands-on use. A recent YouTube talk by someone from PromptLayer addressed this point engagingly:&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/RFKCzGlAU6Q"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;h4&gt;
  
  
  Claude Skills (Agent Skills)
&lt;/h4&gt;

&lt;p&gt;Claude Skills was added in v2.0.22 on October 17. On December 18, it became an open standard as &lt;a href="https://github.com/agentskills/agentskills" rel="noopener noreferrer"&gt;Agent Skills&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Skills have been widely discussed lately. I will skip details since many have explained them. This Code Summit video explains Skills well:&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/CEvIs9y1uog"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;p&gt;You only need to understand the concept of &lt;strong&gt;progressive context disclosure&lt;/strong&gt; for Agent Skills. Context engineering matters here too. Skills enable tool orchestration, and combining that with agent orchestration will gain more attention.&lt;/p&gt;

&lt;p&gt;Anthropic emphasizes these Skills characteristics while designing for portability across Claude Code, Claude Desktop, and beyond. As with MCP (Model Context Protocol), Anthropic excels at developing concepts and features essential to AI agents.&lt;/p&gt;

&lt;h4&gt;
  
  
  Interactive Question Tool
&lt;/h4&gt;

&lt;p&gt;You may not recognize the name "Interactive Question Tool." It is the feature in Plan mode where Claude asks users detailed questions. I adopted this name from the &lt;a href="https://github.com/anthropics/claude-code/blob/main/CHANGELOG.md#2021" rel="noopener noreferrer"&gt;CHANGELOG&lt;/a&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"A video of me trying the newly implemented 'Interactive plan tool' that lets you have a conversation with Claude while planning in Plan mode. Hope the vibe comes through."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;

&lt;iframe class="tweet-embed" id="tweet-1979338989330149754-292" src="https://platform.twitter.com/embed/Tweet.html?id=1979338989330149754"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-1979338989330149754-292');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=1979338989330149754&amp;amp;theme=dark"
  }





&lt;/p&gt;

&lt;p&gt;I find this feature groundbreaking because it clarifies specification boundaries during planning.&lt;/p&gt;

&lt;p&gt;A major cause of AI coding rework was gaps between user-expected specifications and AI implementation. If users could draw clear specification boundaries through prompts or spec documents, problems would not arise. But often those boundaries are ambiguous, causing agents to deviate from user expectations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The Interactive Question Tool lets the AI agent confirm specification details&lt;/strong&gt;, much like a human colleague would. This shift from one-way user input to interactive exchange represents major progress in AI tools and significantly impacts AI coding's future.&lt;/p&gt;

&lt;h4&gt;
  
  
  Plugin Marketplace
&lt;/h4&gt;

&lt;p&gt;Claude Code's Plugin system is another feature I am watching. AI tools are powerful, but many organizations still struggle with team adoption. A major reason is the &lt;strong&gt;AI tool learning curve&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Power users of tools like Claude Code can create their own Skills, Hooks, and custom slash commands, but there is a large gap compared to those unfamiliar with AI tools. This creates personalized CLAUDE.md files and individual variations.&lt;/p&gt;

&lt;p&gt;The Plugin system distributes functionality, making AI tools more accessible for team development. Having already built an ecosystem for easy installation and sharing, like VSCode Marketplace, is a Claude Code strength.&lt;/p&gt;

&lt;p&gt;Creating plugins is simple: just add &lt;code&gt;marketplace.json&lt;/code&gt; and &lt;code&gt;plugin.json&lt;/code&gt; in a &lt;code&gt;.claude-plugin&lt;/code&gt; directory. Here is my demo GitHub project for reference:&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/oikon48" rel="noopener noreferrer"&gt;
        oikon48
      &lt;/a&gt; / &lt;a href="https://github.com/oikon48/cc-frontend-skills" rel="noopener noreferrer"&gt;
        cc-frontend-skills
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
       Claude Code plugin for creating frontend UIs that avoid generic AI aesthetics. (Claude Skills  is written in Japanese)
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Frontend Skills Plugin&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://github.com/oikon48/cc-frontend-skills/LICENSE" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/fdf2982b9f5d7489dcf44570e714e3a15fce6253e0cc6b5aa61a075aac2ff71b/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d79656c6c6f772e737667" alt="License: MIT"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; This project is for demonstrating Claude Skills with Claude Code.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A Claude Code plugin for creating distinctive, production-grade frontend UIs that avoid generic "AI slop" aesthetics. This Skill and Subagent is generated with referring Anthropic blog: &lt;a href="https://www.claude.com/blog/improving-frontend-design-through-skills" rel="nofollow noopener noreferrer"&gt;Improving frontend design through Skills&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Features&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Distinctive typography&lt;/strong&gt; - Effective serif × sans-serif pairings&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Custom color palettes&lt;/strong&gt; - Beyond default Tailwind colors&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Asymmetric layouts&lt;/strong&gt; - 35/65 ratios, overlapping elements&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Purposeful animations&lt;/strong&gt; - Focused on high-impact moments&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Demo&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Left: &lt;strong&gt;With Skills&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Right: Without Skills&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Prompt:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/oikon48/cc-frontend-skills/assets/prompt.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Foikon48%2Fcc-frontend-skills%2Fassets%2Fprompt.png" alt="Prompt"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Result:&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/oikon48/cc-frontend-skills/assets/demo.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Foikon48%2Fcc-frontend-skills%2Fassets%2Fdemo.png" alt="Demo"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Installation&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Execute following &lt;code&gt;/plugin&lt;/code&gt; slash commands in Claude Code.&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Add marketplace&lt;/span&gt;
/plugin marketplace add oikon48/cc-frontend-skills

&lt;span class="pl-c"&gt;&lt;span class="pl-c"&gt;#&lt;/span&gt; Install plugin&lt;/span&gt;
/plugin install frontend-skills@cc-frontend-skills&lt;/pre&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Usage&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Simply make frontend-related requests and the design skill will be applied automatically:&lt;/p&gt;
&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;
&lt;pre class="notranslate"&gt;&lt;code&gt;Build me a flight lookup nextjs web app where the user can put in a flight number and the app gives you the start time, end time, time zones, start&lt;/code&gt;&lt;/pre&gt;…&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/oikon48/cc-frontend-skills" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;




&lt;h3&gt;
  
  
  What Makes Claude Code Excellent
&lt;/h3&gt;

&lt;p&gt;Having reviewed notable CHANGELOG features, I want to address Claude Code's excellence from a tool design perspective. I see many strengths, but I will highlight two.&lt;/p&gt;

&lt;h4&gt;
  
  
  The CLI Tool Approach
&lt;/h4&gt;

&lt;p&gt;One of Claude Code's strengths is being a CLI tool. CLI tools are usable anywhere by any developer.&lt;/p&gt;

&lt;p&gt;Historically, development tools moved from CLI to GUI (IDEs), but in the AI era, rather than returning to CLI, I see it as moving to an Agent UI. In other words:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CLI → GUI → Agent UI&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;While Claude Code appears to be a CLI tool, I personally feel it pioneered the Agent UI concept.&lt;/p&gt;

&lt;p&gt;Claude Code started as &lt;a href="https://x.com/bcherny/status/2004887829252317325" rel="noopener noreferrer"&gt;Boris's side project&lt;/a&gt;, hence its CLI origins. But the CLI design persisted for several reasons, as explained in an Anthropic video:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Targeting the terminal that developers always use&lt;/li&gt;
&lt;li&gt;LLMs enabled a return from rich UI to chat&lt;/li&gt;
&lt;li&gt;Simple CLI lets users focus on tasks&lt;/li&gt;
&lt;li&gt;CLI is the thinnest wrapper around the model, keeping things clean&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/vLIDHi-1PVU"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;h4&gt;
  
  
  The Claude Code Harness
&lt;/h4&gt;

&lt;p&gt;Claude Code's growing prominence in AI coding stems from the harness's completeness.&lt;/p&gt;

&lt;p&gt;Throughout this article, I have used "AI model" and "harness." These terms appear in Anthropic's video &lt;a href="https://www.youtube.com/watch?v=iF9iV4xponk" rel="noopener noreferrer"&gt;The future of agentic coding with Claude Code&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/iF9iV4xponk"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;p&gt;AI tools split into AI model and harness, with capabilities emerging from their combination. The video &lt;strong&gt;compares the AI model to a horse and Claude Code to a harness&lt;/strong&gt; (horse equipment), explaining how it controls and guides the AI tool. I love this metaphor and frequently reference it in presentations.&lt;/p&gt;

&lt;p&gt;The Claude Code harness is well-designed to appropriately provide tools, prompts, and context to the Claude model, guiding it toward task completion. This differentiates it significantly from other AI tools.&lt;/p&gt;

&lt;h3&gt;
  
  
  Current Challenges
&lt;/h3&gt;

&lt;p&gt;I have focused on positives, but challenges certainly exist. Many remain. Here are some major ones.&lt;/p&gt;

&lt;h4&gt;
  
  
  Context Window Size
&lt;/h4&gt;

&lt;p&gt;The first challenge is context window size. GPT-5.2 has 400k tokens, Gemini 3 Pro has 1M, while Claude Opus 4.5 remains at 200k. This &lt;strong&gt;significantly constrains users&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Claude Code mitigates context window issues through Subagents and recently implemented rules, but even the harness's power cannot fully hide this problem.&lt;/p&gt;

&lt;p&gt;Fortunately, I had access to Claude Sonnet 4.5 [1M] and used it primarily before Opus 4.5 arrived. I remember feeling how much easier things became with a larger context window. Conversely, imagine what happens when Claude gets a standard 1M context window.&lt;/p&gt;

&lt;h4&gt;
  
  
  Compaction Quality
&lt;/h4&gt;

&lt;p&gt;Even accepting Claude's current 200k context window, Claude Code's context compaction (&lt;code&gt;/compact&lt;/code&gt;, auto-compact) has room for improvement.&lt;/p&gt;

&lt;p&gt;I have felt Codex CLI handles compaction better in some situations. &lt;strong&gt;Claude Code seems to simply summarize the session&lt;/strong&gt; unless you explicitly specify compaction instructions.&lt;/p&gt;

&lt;p&gt;If model context windows grow larger, compaction may become less relevant. But for now, you either need compaction instructions or frequent &lt;code&gt;/clear&lt;/code&gt; commands to keep the context window clean.&lt;/p&gt;

&lt;h4&gt;
  
  
  Knowledge Cutoff
&lt;/h4&gt;

&lt;p&gt;This universal model problem affects Claude and others: knowledge cutoff impact appears frequently. Specifically, I often encounter bugs from models not knowing the latest libraries or versions.&lt;/p&gt;

&lt;p&gt;Workarounds include using WebSearch or Context7 MCP to fetch current information, but ideally the Claude Code harness would handle this automatically. As &lt;a href="https://simonwillison.net/2025/Dec/28/actions-latest/" rel="noopener noreferrer"&gt;Simon Willison's recent article&lt;/a&gt; suggested, &lt;strong&gt;centralizing version information and loading it via Skills when needed&lt;/strong&gt; seems like a good approach.&lt;/p&gt;

&lt;p&gt;Claude Code is still a product barely ten months old. I look forward to watching it grow.&lt;/p&gt;

&lt;h3&gt;
  
  
  Should You Use Third-Party Tools?
&lt;/h3&gt;

&lt;p&gt;Claude Code's user base grew dramatically this year, and third-party tools proliferated. Notable examples include awesome-claude series collecting custom slash commands and Subagents (various authors), plus complex harness mechanisms built with Claude Hooks.&lt;/p&gt;

&lt;p&gt;My personal opinion: use these third-party tools cautiously.&lt;/p&gt;

&lt;p&gt;Claude Code works through the combination of the Claude model and Claude Code harness. &lt;strong&gt;Many third-party tools essentially build additional harness layers&lt;/strong&gt; outside the existing harness.&lt;/p&gt;

&lt;p&gt;Claude model and tool evolution is dramatic, and Claude Code's behavior changes significantly week to week. Unless third-party tools are maintained to keep pace, many become unnecessary harness overhead.&lt;/p&gt;

&lt;p&gt;Given that future Claude Code versions may incorporate and improve upon these features, I personally do not recommend heavy third-party tool dependence.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Future of Claude Code
&lt;/h2&gt;

&lt;p&gt;In just ten months of 2025, Claude Code evolved dramatically. Having shared my personal views on Claude Code's present, I want to speculate about 2026.&lt;/p&gt;

&lt;h3&gt;
  
  
  Evolution Trajectories
&lt;/h3&gt;

&lt;p&gt;Claude Code has established its position as an AI coding tool, but significant evolution potential remains. Drawing from hints gathered when I asked Claude Code developer Boris at the recent Claude Code Meetup Tokyo, I will explore possible directions.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I asked Boris Cherny about Claude Code's future direction at the Claude Code Meetup Tokyo Q&amp;amp;A. I was curious about orchestration and scheduling. His answer: He is very interested in two things—'Long running' and 'Swarm'. Both seem to be at the demo stage. Quite a hot topic."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG8w-gjNa4AABg6x%3Fformat%3Djpg%26name%3Dmedium" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG8w-gjNa4AABg6x%3Fformat%3Djpg%26name%3Dmedium" alt="Claude Code Meetup Tokyo"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;

&lt;iframe class="tweet-embed" id="tweet-2003054927862718844-721" src="https://platform.twitter.com/embed/Tweet.html?id=2003054927862718844"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-2003054927862718844-721');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=2003054927862718844&amp;amp;theme=dark"
  }





&lt;/p&gt;

&lt;h4&gt;
  
  
  Long-Running Tasks
&lt;/h4&gt;

&lt;p&gt;Claude Code already acts quite autonomously, but not completely.&lt;/p&gt;

&lt;p&gt;For tasks like reviewing an entire codebase and performing certain operations, Claude Code sometimes stops before completion. Users must then say "Continue, you're not done yet" to resume.&lt;/p&gt;

&lt;p&gt;Future improvements should enable Claude Code to run longer and complete tasks.&lt;/p&gt;

&lt;p&gt;Notably, an official Anthropic plugin called &lt;a href="https://github.com/anthropics/claude-plugins-official/tree/main/plugins/ralph-wiggum" rel="noopener noreferrer"&gt;ralph-wiggum&lt;/a&gt; already enables long-running execution. This may become standard or improved.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"The ralph-wiggum plugin is a mechanism that creates a 'User prompt submit hook' to automatically inject '/ralph-loop' as user input. While in ralph-loop, it infinitely injects '/continue' as user input when Claude's turn ends."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG9ORHDobgAEAVtI%3Fformat%3Djpg%26name%3Dmedium" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG9ORHDobgAEAVtI%3Fformat%3Djpg%26name%3Dmedium" alt="ralph-wiggum plugin"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;

&lt;iframe class="tweet-embed" id="tweet-2005105826730836374-328" src="https://platform.twitter.com/embed/Tweet.html?id=2005105826730836374"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-2005105826730836374-328');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=2005105826730836374&amp;amp;theme=dark"
  }





&lt;/p&gt;

&lt;h4&gt;
  
  
  Swarming (Orchestrated Execution)
&lt;/h4&gt;

&lt;p&gt;Orchestrated execution was also mentioned. This differs from parallel Subagent execution.&lt;/p&gt;

&lt;p&gt;Around June 2025, using tmux to run multiple Claude Code instances with Manager and Worker roles for orchestration became a topic of discussion.&lt;/p&gt;

&lt;p&gt;Claude Code may eventually support Swarming natively. I personally suspect the undocumented delegate mode may be part of swarming functionality.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"Claude Code 2.0.71 quietly added a mysterious 'delegate mode'"&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG8U1fkeaIAABAyt%3Fformat%3Djpg%26name%3Dmedium" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG8U1fkeaIAABAyt%3Fformat%3Djpg%26name%3Dmedium" alt="delegate mode"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;

&lt;iframe class="tweet-embed" id="tweet-2001064637845135572-389" src="https://platform.twitter.com/embed/Tweet.html?id=2001064637845135572"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-2001064637845135572-389');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=2001064637845135572&amp;amp;theme=dark"
  }





&lt;/p&gt;

&lt;h4&gt;
  
  
  External Tool Integration
&lt;/h4&gt;

&lt;p&gt;This is my personal prediction, not from Boris.&lt;/p&gt;

&lt;p&gt;Currently, Claude Code has standard tools plus Skills and MCP tools that it uses autonomously. However, there is room for improvement in selecting the right tool at the right time.&lt;/p&gt;

&lt;p&gt;MCP tools in particular are criticized for consuming context windows, suggesting tool call mechanisms need enhancement. This topic came up at Anthropic Builder Summit Tokyo, with discussions about using programs to mediate MCP tool calls.&lt;/p&gt;

&lt;p&gt;Regarding MCP, a beta feature for dynamically loading MCP tools has been implemented and is available for testing.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;"I saw a post saying that the feature to dynamically load MCP tools in Claude Code is available as a beta release, so I tried it. Setting these two environment variables: ENABLE_TOOL_SEARCH=true and ENABLE_EXPERIMENTAL_MCP_CLI=false lets you try it out. When I tested it, MCP tool context became 0 and I confirmed tools are loaded dynamically when used (see next post). This will likely be included in a Claude Code release soon."&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG9YK1_oaYAAJ29K%3Fformat%3Djpg%26name%3Dmedium" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG9YK1_oaYAAJ29K%3Fformat%3Djpg%26name%3Dmedium" alt="MCP dynamic loading comparison"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;

&lt;iframe class="tweet-embed" id="tweet-2005803922167083152-248" src="https://platform.twitter.com/embed/Tweet.html?id=2005803922167083152"&gt;
&lt;/iframe&gt;

  // Detect dark theme
  var iframe = document.getElementById('tweet-2005803922167083152-248');
  if (document.body.className.includes('dark-theme')) {
    iframe.src = "https://platform.twitter.com/embed/Tweet.html?id=2005803922167083152&amp;amp;theme=dark"
  }





&lt;/p&gt;

&lt;p&gt;Expanding further on external tools: Physical AI will likely gain more attention in 2026. Robots and autonomous vehicles are already exciting areas, and I expect Claude Code to eventually perceive and interact with the physical world through external sensors.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Value of Following Claude Code
&lt;/h3&gt;

&lt;p&gt;Claude Code is an excellent tool. Since Opus 4.5's release especially, it has pulled ahead. But other AI tools have also improved significantly, and honestly, users should pick whatever suits their use case and preferences.&lt;/p&gt;

&lt;p&gt;Even in this era of competing AI tools, &lt;strong&gt;Claude Code (and Anthropic) consistently sets milestones at the frontier&lt;/strong&gt;, making it personally worthwhile to use and follow. At minimum, Claude Code led AI tools in 2025. The features and mechanisms Claude Code released will undoubtedly be recorded when we look back on engineering history years from now.&lt;/p&gt;

&lt;p&gt;For those planning to work in engineering for the next decade or more, Claude Code is worth following.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I wrote this article to organize my personal thoughts from watching Claude Code throughout the year. I deeply realize how impactful this year was for me personally. I am genuinely grateful to be an active engineer during such fascinating times.&lt;/p&gt;

&lt;p&gt;Next year feels like it will accelerate even more, but I intend to keep enjoying myself while occasionally gritting my teeth to avoid being left behind.&lt;/p&gt;

&lt;p&gt;Side note: I was inspired to write this by the following article. It is long but excellent, so please take the time to read it in full:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sankalp.bearblog.dev/my-experience-with-claude-code-20-and-how-to-get-better-at-using-coding-agents/" rel="noopener noreferrer"&gt;Sankalp's Experience with Claude Code 2.0&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;If you found this article valuable, follow the author on &lt;a href="https://x.com/oikon48" rel="noopener noreferrer"&gt;X (@oikon48)&lt;/a&gt; for ongoing Claude Code insights and updates.&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;h3&gt;
  
  
  GitHub
&lt;/h3&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/anthropics" rel="noopener noreferrer"&gt;
        anthropics
      &lt;/a&gt; / &lt;a href="https://github.com/anthropics/claude-code" rel="noopener noreferrer"&gt;
        claude-code
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows - all through natural language commands.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Claude Code&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer nofollow" href="https://camo.githubusercontent.com/92c4b317cff472ae3476218ac6a59a4e1e2071b074166d0a003953d6a4408ff1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4e6f64652e6a732d31382532422d627269676874677265656e3f7374796c653d666c61742d737175617265"&gt;&lt;img src="https://camo.githubusercontent.com/92c4b317cff472ae3476218ac6a59a4e1e2071b074166d0a003953d6a4408ff1/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4e6f64652e6a732d31382532422d627269676874677265656e3f7374796c653d666c61742d737175617265" alt=""&gt;&lt;/a&gt; &lt;a href="https://www.npmjs.com/package/@anthropic-ai/claude-code" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/54fc0e51d112658ac0d5ef0a25e03c9ebcbf5bf0068b35d818cdc18825f97bf8/68747470733a2f2f696d672e736869656c64732e696f2f6e706d2f762f40616e7468726f7069632d61692f636c617564652d636f64652e7376673f7374796c653d666c61742d737175617265" alt="npm"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Claude Code is an agentic coding tool that lives in your terminal, understands your codebase, and helps you code faster by executing routine tasks, explaining complex code, and handling git workflows -- all through natural language commands. Use it in your terminal, IDE, or tag &lt;a class="mentioned-user" href="https://dev.to/claude"&gt;@claude&lt;/a&gt; on Github.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Learn more in the &lt;a href="https://code.claude.com/docs/en/overview" rel="nofollow noopener noreferrer"&gt;official documentation&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/anthropics/claude-code/./demo.gif"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fgithub.com%2Fanthropics%2Fclaude-code%2F.%2Fdemo.gif"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Get started&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="markdown-alert markdown-alert-note"&gt;
&lt;p class="markdown-alert-title"&gt;Note&lt;/p&gt;
&lt;p&gt;Installation via npm is deprecated. Use one of the recommended methods below.&lt;/p&gt;
&lt;/div&gt;
&lt;p&gt;For more installation options, uninstall steps, and troubleshooting, see the &lt;a href="https://code.claude.com/docs/en/setup" rel="nofollow noopener noreferrer"&gt;setup documentation&lt;/a&gt;.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Install Claude Code:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;MacOS/Linux (Recommended):&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;curl -fsSL https://claude.ai/install.sh &lt;span class="pl-k"&gt;|&lt;/span&gt; bash&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Homebrew (MacOS/Linux):&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;brew install --cask claude-code&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Windows (Recommended):&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight highlight-source-powershell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;irm https:&lt;span class="pl-k"&gt;//&lt;/span&gt;claude.ai&lt;span class="pl-k"&gt;/&lt;/span&gt;install.ps1 &lt;span class="pl-k"&gt;|&lt;/span&gt; iex&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;WinGet (Windows):&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight highlight-source-powershell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;winget install Anthropic.ClaudeCode&lt;/pre&gt;

&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;NPM (Deprecated):&lt;/strong&gt;&lt;/p&gt;
&lt;div class="highlight highlight-source-shell notranslate position-relative overflow-auto js-code-highlight"&gt;
&lt;pre&gt;npm install -g @anthropic-ai/claude-code&lt;/pre&gt;

&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Navigate to your project directory and run &lt;code&gt;claude&lt;/code&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Plugins&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;This repository includes several Claude Code plugins that extend functionality with custom commands and agents. See the &lt;a href="https://github.com/anthropics/claude-code/./plugins/README.md" rel="noopener noreferrer"&gt;plugins&lt;/a&gt;…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/anthropics/claude-code" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;




&lt;p&gt;&lt;a href="https://github.com/anthropics/claude-code/issues/6235" rel="noopener noreferrer"&gt;GitHub Issue: AGENTS.md Support&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/agentskills" rel="noopener noreferrer"&gt;
        agentskills
      &lt;/a&gt; / &lt;a href="https://github.com/agentskills/agentskills" rel="noopener noreferrer"&gt;
        agentskills
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Specification and documentation for Agent Skills
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Agent Skills&lt;/h1&gt;

&lt;/div&gt;
&lt;p&gt;&lt;a href="https://agentskills.io" rel="nofollow noopener noreferrer"&gt;Agent Skills&lt;/a&gt; are a simple, open format for giving agents new capabilities and expertise.&lt;/p&gt;
&lt;p&gt;Skills are folders of instructions, scripts, and resources that agents can discover and use to perform better at specific tasks. Write once, use everywhere.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Getting Started&lt;/h2&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://agentskills.io" rel="nofollow noopener noreferrer"&gt;Documentation&lt;/a&gt;&lt;/strong&gt; — Guides and tutorials&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://agentskills.io/specification" rel="nofollow noopener noreferrer"&gt;Specification&lt;/a&gt;&lt;/strong&gt; — Format details&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://github.com/anthropics/skills" rel="noopener noreferrer"&gt;Example Skills&lt;/a&gt;&lt;/strong&gt; — See what's possible&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;a href="https://discord.gg/MKPE9g8aUy" rel="nofollow noopener noreferrer"&gt;Discord&lt;/a&gt;&lt;/strong&gt; — Join the discussion!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This repo contains the specification, documentation, and reference SDK. Also see a list of example skills &lt;a href="https://github.com/anthropics/skills" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;About&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Agent Skills is an open format maintained by &lt;a href="https://anthropic.com" rel="nofollow noopener noreferrer"&gt;Anthropic&lt;/a&gt; and open to contributions from the community.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;License&lt;/h2&gt;

&lt;/div&gt;
&lt;p&gt;Code in this repository is licensed under &lt;a href="https://github.com/agentskills/agentskills/LICENSE" rel="noopener noreferrer"&gt;Apache 2.0&lt;/a&gt;. Documentation is licensed under &lt;a href="https://creativecommons.org/licenses/by/4.0/" rel="nofollow noopener noreferrer"&gt;CC-BY-4.0&lt;/a&gt;. See individual directories for details.&lt;/p&gt;
&lt;/div&gt;



&lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/agentskills/agentskills" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;





&lt;p&gt;

&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/anthropics" rel="noopener noreferrer"&gt;
        anthropics
      &lt;/a&gt; / &lt;a href="https://github.com/anthropics/claude-plugins-official" rel="noopener noreferrer"&gt;
        claude-plugins-official
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Official, Anthropic-managed directory of high quality Claude Code Plugins.
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Claude Code Plugins Directory&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;A curated directory of high-quality plugins for Claude Code.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;⚠️ Important:&lt;/strong&gt; Make sure you trust a plugin before installing, updating, or using it. Anthropic does not control what MCP servers, files, or other software are included in plugins and cannot verify that they will work as intended or that they won't change. See each plugin's homepage for more information.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Structure&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/plugins&lt;/code&gt;&lt;/strong&gt; - Internal plugins developed and maintained by Anthropic&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;/external_plugins&lt;/code&gt;&lt;/strong&gt; - Third-party plugins from partners and the community&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Installation&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;Plugins can be installed directly from this marketplace via Claude Code's plugin system.&lt;/p&gt;
&lt;p&gt;To install, run &lt;code&gt;/plugin install {plugin-name}@claude-plugins-official&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;or browse for the plugin in &lt;code&gt;/plugin &amp;gt; Discover&lt;/code&gt;&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Contributing&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Internal Plugins&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;Internal plugins are developed by Anthropic team members. See &lt;code&gt;/plugins/example-plugin&lt;/code&gt; for a reference implementation.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;External Plugins&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;Third-party partners can submit plugins for inclusion in the marketplace. External plugins must meet quality and security standards for approval…&lt;/p&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/anthropics/claude-plugins-official" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;




&lt;h3&gt;
  
  
  External Articles
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://claude.com/blog/max-plan" rel="noopener noreferrer"&gt;Claude Max Plan Announcement&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.anthropic.com/news/claude-opus-4-5" rel="noopener noreferrer"&gt;Claude Opus 4.5 Announcement&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://simonwillison.net/2025/Dec/28/actions-latest/" rel="noopener noreferrer"&gt;Simon Willison - actions-latest&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://sankalp.bearblog.dev/my-experience-with-claude-code-20-and-how-to-get-better-at-using-coding-agents/" rel="noopener noreferrer"&gt;Sankalp's Experience with Claude Code 2.0&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Videos
&lt;/h3&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/iF9iV4xponk"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/vLIDHi-1PVU"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/CEvIs9y1uog"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

&lt;p&gt;

  &lt;iframe src="https://www.youtube.com/embed/RFKCzGlAU6Q"&gt;
  &lt;/iframe&gt;


&lt;/p&gt;

</description>
      <category>claude</category>
      <category>ai</category>
      <category>claudcode</category>
      <category>anthropic</category>
    </item>
    <item>
      <title>24 Claude Code Tips: #claude_code_advent_calendar</title>
      <dc:creator>Oikon</dc:creator>
      <pubDate>Thu, 25 Dec 2025 13:26:51 +0000</pubDate>
      <link>https://dev.to/oikon/24-claude-code-tips-claudecodeadventcalendar-52b5</link>
      <guid>https://dev.to/oikon/24-claude-code-tips-claudecodeadventcalendar-52b5</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;Claude Code ships new features almost weekly, and the documentation often struggles to keep pace. If you have been using Claude Code since its early days, you know the feeling of discovering a powerful feature months after it was released, hidden in a CHANGELOG or mentioned casually on X.&lt;/p&gt;

&lt;p&gt;I have been tracking Claude Code since March 2025, documenting every update, testing every feature, and sharing insights with the developer community. When December arrived, I decided to compile my knowledge into a Claude Code Advent Calendar: 24 days, 24 essential tips, shared daily on X with the hashtag &lt;a href="https://x.com/hashtag/claude_code_advent_calendar" rel="noopener noreferrer"&gt;#claude_code_advent_calendar&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;This article consolidates all 24 tips into a single comprehensive guide. Whether you are a Claude Code newcomer or a power user, you will find actionable insights to level up your AI-assisted development workflow.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/oikon48/status/2003798309354549671?s=20" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fonidt3h0u6gjs573iz9k.png" alt="x post" width="800" height="888"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Quick Navigation
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Day&lt;/th&gt;
&lt;th&gt;Topic&lt;/th&gt;
&lt;th&gt;Day&lt;/th&gt;
&lt;th&gt;Topic&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1&lt;/td&gt;
&lt;td&gt;Opus 4.5 Migration Guide&lt;/td&gt;
&lt;td&gt;13&lt;/td&gt;
&lt;td&gt;Sandbox for rm -rf Prevention&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2&lt;/td&gt;
&lt;td&gt;Claude Code Statusline&lt;/td&gt;
&lt;td&gt;14&lt;/td&gt;
&lt;td&gt;Hooks for Sensitive Data Filtering&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;3&lt;/td&gt;
&lt;td&gt;Send Tasks to Web with &amp;amp;&lt;/td&gt;
&lt;td&gt;15&lt;/td&gt;
&lt;td&gt;Hooks for Code Formatting&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;4&lt;/td&gt;
&lt;td&gt;Thinking Keywords&lt;/td&gt;
&lt;td&gt;16&lt;/td&gt;
&lt;td&gt;External Editor with Ctrl + G&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;5&lt;/td&gt;
&lt;td&gt;AGENTS.md Support&lt;/td&gt;
&lt;td&gt;17&lt;/td&gt;
&lt;td&gt;Plan Mode&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;6&lt;/td&gt;
&lt;td&gt;On the Web Setup&lt;/td&gt;
&lt;td&gt;18&lt;/td&gt;
&lt;td&gt;GIF Creation with Claude in Chrome&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;7&lt;/td&gt;
&lt;td&gt;MCP Tool Context Consumption&lt;/td&gt;
&lt;td&gt;19&lt;/td&gt;
&lt;td&gt;Agent Skills Best Practices&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;Skill Creator&lt;/td&gt;
&lt;td&gt;20&lt;/td&gt;
&lt;td&gt;Auto-compact Buffer Size&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;Skills + Subagents&lt;/td&gt;
&lt;td&gt;21&lt;/td&gt;
&lt;td&gt;Async Subagents&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;Project Rules&lt;/td&gt;
&lt;td&gt;22&lt;/td&gt;
&lt;td&gt;Code Action + Agent Skills&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;11&lt;/td&gt;
&lt;td&gt;CLAUDE.md Loading&lt;/td&gt;
&lt;td&gt;23&lt;/td&gt;
&lt;td&gt;Parallel Execution&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;12&lt;/td&gt;
&lt;td&gt;Preventing rm -rf Disasters&lt;/td&gt;
&lt;td&gt;24&lt;/td&gt;
&lt;td&gt;Claude Code Ecosystem&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h2&gt;
  
  
  Day 1: Opus 4.5 Migration Guide
&lt;/h2&gt;

&lt;p&gt;Anthropic maintains an official Skills plugin for migrating prompts from older Claude models to Opus 4.5. This migration guide reveals interesting behavioral differences in the latest model.&lt;/p&gt;

&lt;p&gt;The migration addresses several tendencies specific to Opus 4.5:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Excessive tool invocations when unnecessary&lt;/li&gt;
&lt;li&gt;Over-engineering solutions&lt;/li&gt;
&lt;li&gt;Insufficient code exploration&lt;/li&gt;
&lt;li&gt;Frontend design quality variations&lt;/li&gt;
&lt;li&gt;Over-reaction to "think" keywords in prompts&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Understanding these tendencies helps you craft more effective prompts. Opus 4.5 aggressively uses tools, which can fill your context window even when tool calls are not required. Monitor your agent's behavior closely when switching models.&lt;/p&gt;

&lt;p&gt;Find the migration plugin at: &lt;a href="https://github.com/anthropics/claude-code/tree/main/plugins/claude-opus-4-5-migration" rel="noopener noreferrer"&gt;anthropics/claude-code/plugins/claude-opus-4-5-migration&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG7EhDjGagAArLQM%3Fformat%3Djpg%26name%3D4096x4096" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG7EhDjGagAArLQM%3Fformat%3Djpg%26name%3D4096x4096" alt="Day 1: Opus 4.5 Migration Guide" width="2098" height="1556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/oikon48/status/1995541792746602606" rel="noopener noreferrer"&gt;Original X post&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 2: Claude Code Statusline
&lt;/h2&gt;

&lt;p&gt;The statusline feature displays useful information below the chat input, including model name, Git branch, and custom metrics.&lt;/p&gt;

&lt;p&gt;Configure it with &lt;code&gt;/statusline &amp;lt;content&amp;gt;&lt;/code&gt; or add it to your settings.json:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"statusLine"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"bun x ccusage statusline"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This configuration uses the ccusage tool to display your API usage directly in the Claude Code interface. The statusline is a small but impactful quality-of-life feature that many users overlook.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG7KOLD7a8AARe0N%3Fformat%3Djpg%26name%3Dmedium" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG7KOLD7a8AARe0N%3Fformat%3Djpg%26name%3Dmedium" alt="Day 2: Claude Code Statusline" width="1152" height="1126"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/oikon48/status/1995821119467913268" rel="noopener noreferrer"&gt;Original X post&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 3: Send Tasks to Web with &amp;amp;
&lt;/h2&gt;

&lt;p&gt;Starting with Claude Code v2.0.45, prefixing your prompt with &lt;code&gt;&amp;amp;&lt;/code&gt; sends the task to Claude Code on the Web for background processing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqomxs6kj8yqttfcqopl9.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqomxs6kj8yqttfcqopl9.gif" alt="Sending task to Claude Code on the Web with &amp;amp; prefix" width="320" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Claude Code on the Web executes tasks in a remote sandbox environment. You can also transfer tasks from Web back to your local CLI using the "Open from CLI" button. The model specified in your local environment carries over to the Web session.&lt;/p&gt;

&lt;p&gt;This feature is particularly useful for offloading smaller tasks while continuing work on your main project locally.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/oikon48/status/1996177293551747577" rel="noopener noreferrer"&gt;Original X post&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 4: Thinking Keywords
&lt;/h2&gt;

&lt;p&gt;Extended thinking mode enables Claude to perform internal reasoning for complex tasks. You can toggle it with Tab in the interface.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr4hswcti8c1suxqwafak.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr4hswcti8c1suxqwafak.gif" alt="Thinking mode toggle with ultrathink keyword" width="480" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here is the critical insight many users miss: only &lt;code&gt;ultrathink&lt;/code&gt; triggers extended thinking mode now. Keywords that previously worked have been disabled:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Works: &lt;code&gt;ultrathink&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Does NOT work: &lt;code&gt;think&lt;/code&gt;, &lt;code&gt;think hard&lt;/code&gt;, &lt;code&gt;think deeply&lt;/code&gt;, or translated equivalents&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This change occurred when Claude Code v2.0.0 introduced the thinking mode toggle. Even Anthropic engineers were unaware of this change initially. The official documentation was only updated on December 13, 2025, two months after the change.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/oikon48/status/1996535955625533508" rel="noopener noreferrer"&gt;Original X post&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 5: AGENTS.md Support
&lt;/h2&gt;

&lt;p&gt;Claude Code does not officially support AGENTS.md. This has been an ongoing discussion in &lt;a href="https://github.com/anthropics/claude-code/issues/6235" rel="noopener noreferrer"&gt;GitHub issue #6235&lt;/a&gt; since August.&lt;/p&gt;

&lt;p&gt;Two workarounds exist. First, you can import AGENTS.md from within CLAUDE.md using the &lt;code&gt;@AGENTS.md&lt;/code&gt; syntax. Verify the import worked with the &lt;code&gt;/memory&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;Alternatively, create a symbolic link: &lt;code&gt;ln -s AGENTS.md CLAUDE.md&lt;/code&gt;. This makes Claude Code read AGENTS.md content as if it were CLAUDE.md.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG7ZjsvBa4AAIYmv%3Fformat%3Djpg%26name%3Dmedium" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG7ZjsvBa4AAIYmv%3Fformat%3Djpg%26name%3Dmedium" alt="Day 5: AGENTS.md Support" width="1200" height="850"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/oikon48/status/1996898343784763479" rel="noopener noreferrer"&gt;Original X post&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 6: Claude Code on the Web Setup
&lt;/h2&gt;

&lt;p&gt;Claude Code on the Web runs in a remote sandbox, which means your local setup does not transfer automatically. However, you can replicate your environment using SessionStart Hooks.&lt;/p&gt;

&lt;p&gt;The environment variable &lt;code&gt;CLAUDE_CODE_REMOTE&lt;/code&gt; indicates when Claude Code runs in the remote Web environment. Create a SessionStart Hook that checks this variable and runs your setup script only in remote sessions.&lt;/p&gt;

&lt;p&gt;Claude Code on the Web includes a built-in &lt;code&gt;session-start-hooks&lt;/code&gt; feature specifically for this purpose. Reference the &lt;a href="https://code.claude.com/docs/en/claude-code-on-the-web" rel="noopener noreferrer"&gt;official documentation&lt;/a&gt; for implementation details.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG7ew2JZa4AAbPBx%3Fformat%3Djpg%26name%3Dmedium" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG7ew2JZa4AAbPBx%3Fformat%3Djpg%26name%3Dmedium" alt="Day 6: Claude Code on the Web Setup" width="1200" height="739"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/oikon48/status/1997261626517692850" rel="noopener noreferrer"&gt;Original X post&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 7: MCP Tool Context Consumption
&lt;/h2&gt;

&lt;p&gt;MCP tools consume context window space just by being available, even when not used. Tool descriptions are loaded into the agent's context, and some tools consume 8-30% of your available context.&lt;/p&gt;

&lt;p&gt;Use the &lt;code&gt;/context&lt;/code&gt; command to see how much space each tool occupies. Browser automation MCP tools are particularly context-hungry.&lt;/p&gt;

&lt;p&gt;A common misconception is that using Skills eliminates this problem. It does not. As long as MCP tools are registered in the agent's context, they consume space regardless of how you invoke them. The only way to reduce this overhead is to use equivalent scripts or API calls within Skills instead of MCP tools, or simply remove unused MCP servers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG7fqCBgbUAAGu5u%3Fformat%3Djpg%26name%3Dmedium" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG7fqCBgbUAAGu5u%3Fformat%3Djpg%26name%3Dmedium" alt="Day 7: MCP Tool Context Consumption" width="986" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/oikon48/status/1997623622438174852" rel="noopener noreferrer"&gt;Original X post&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 8: Skill Creator
&lt;/h2&gt;

&lt;p&gt;Skill Creator is a meta-skill that generates new Skills. Install it from the official Anthropic plugins:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/plugin marketplace add anthropics/skills
/plugin install example-skills@anthropic-agent-skills
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After restarting Claude Code, request "Create a skill for [your use case]" to invoke the skill-creator. This provides a solid starting point for custom Skills.&lt;/p&gt;

&lt;p&gt;Note that skill-creator has existed since October 2025. While it generates functional Skills quickly, the output may not follow all best practices covered in Day 19. Treat its output as a foundation for further refinement.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG7pH8aqbYAEXgtW%3Fformat%3Djpg%26name%3Dmedium" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG7pH8aqbYAEXgtW%3Fformat%3Djpg%26name%3Dmedium" alt="Day 8: Skill Creator" width="1200" height="917"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/oikon48/status/1997988839571530111" rel="noopener noreferrer"&gt;Original X post&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 9: Skills + Subagents
&lt;/h2&gt;

&lt;p&gt;Skills provide knowledge and workflows. Subagents execute specialized tasks. These two features complement each other and can be combined.&lt;/p&gt;

&lt;p&gt;Add Skills to a Subagent definition using YAML frontmatter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;skills&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;frontend-design-system&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;testing-patterns&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="c1"&gt;# Fullstack Developer Subagent&lt;/span&gt;
&lt;span class="nn"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Skills defined in the frontmatter automatically load into the Subagent's context when invoked. The &lt;a href="https://code.claude.com/docs/en/sub-agents#file-format" rel="noopener noreferrer"&gt;official Subagent documentation&lt;/a&gt; covers additional frontmatter options.&lt;/p&gt;

&lt;p&gt;This combination became more relevant after Codex CLI added Skills support, increasing interest in Skills across the AI coding assistant ecosystem.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG7uCi1HbcAAZIRF%3Fformat%3Djpg%26name%3Dmedium" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG7uCi1HbcAAZIRF%3Fformat%3Djpg%26name%3Dmedium" alt="Day 9: Skills + Subagents" width="1106" height="692"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/oikon48/status/1998347895431397638" rel="noopener noreferrer"&gt;Original X post&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 10: Project Rules
&lt;/h2&gt;

&lt;p&gt;Version 2.0.64 introduced Project Rules as an alternative to CLAUDE.md. Store topic-specific rules in &lt;code&gt;.claude/rules/&lt;/code&gt; as Markdown files.&lt;/p&gt;

&lt;p&gt;Organize rules by concern:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code style guidelines&lt;/li&gt;
&lt;li&gt;Testing conventions&lt;/li&gt;
&lt;li&gt;Security requirements&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rules support YAML frontmatter for conditional application:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;paths&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;src/api/**/*.ts&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="c1"&gt;# API Development Rules&lt;/span&gt;
&lt;span class="nn"&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When Claude Code operates on files matching the glob pattern, the corresponding rules load dynamically. This provides more granular control than a single CLAUDE.md file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG7zdCyIbMAAFmCs%3Fformat%3Djpg%26name%3Dmedium" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG7zdCyIbMAAFmCs%3Fformat%3Djpg%26name%3Dmedium" alt="Day 10: Project Rules" width="1200" height="940"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/oikon48/status/1998717425223872974" rel="noopener noreferrer"&gt;Original X post&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 11: CLAUDE.md Loading
&lt;/h2&gt;

&lt;p&gt;Claude Code loads project CLAUDE.md from two locations at startup:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;./CLAUDE.md&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;./.claude/CLAUDE.md&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can also place CLAUDE.md files in nested directories. These are not loaded at startup but are read when Claude Code operates within that directory.&lt;/p&gt;

&lt;p&gt;With Project Rules (Day 10), you now have multiple options for organizing project instructions. Use nested CLAUDE.md for directory-specific context and Project Rules for cross-cutting concerns that apply to specific file patterns.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG74jQg4asAApwpz%3Fformat%3Djpg%26name%3Dmedium" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG74jQg4asAApwpz%3Fformat%3Djpg%26name%3Dmedium" alt="Day 11: CLAUDE.md Loading" width="1194" height="802"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/oikon48/status/1999075187237781744" rel="noopener noreferrer"&gt;Original X post&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 12: Preventing rm -rf Disasters
&lt;/h2&gt;

&lt;p&gt;Stories of AI agents executing &lt;code&gt;rm -rf&lt;/code&gt; and deleting important directories appear regularly on Reddit and X. New Claude Code users should configure safety guards immediately.&lt;/p&gt;

&lt;p&gt;Add permission restrictions to &lt;code&gt;~/.claude/settings.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"permissions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"deny"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;"rm"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DROP TABLE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DELETE FROM"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The &lt;code&gt;permissions.deny&lt;/code&gt; setting blocks specified commands entirely. For more flexibility, use &lt;code&gt;permissions.ask&lt;/code&gt; to require confirmation before executing dangerous commands. These settings take precedence even when using &lt;code&gt;--dangerously-skip-permissions&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Reference the Reddit incident that prompted this tip: &lt;a href="https://www.reddit.com/r/ClaudeAI/comments/1pgxckk/claude_cli_deleted_my_entire_home_directory_wiped/" rel="noopener noreferrer"&gt;Claude CLI deleted my entire home directory&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG79okHeacAAda1o%3Fformat%3Djpg%26name%3Dmedium" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG79okHeacAAda1o%3Fformat%3Djpg%26name%3Dmedium" alt="Day 12: Preventing rm -rf Disasters" width="951" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/oikon48/status/1999441853423231428" rel="noopener noreferrer"&gt;Original X post&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 13: Sandbox for rm -rf Prevention
&lt;/h2&gt;

&lt;p&gt;The &lt;code&gt;/sandbox&lt;/code&gt; command restricts Claude Code's file system and network access to your working directory and explicitly permitted paths.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fob35m3xkhwqh8y04bmcf.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fob35m3xkhwqh8y04bmcf.gif" alt="Sandbox preventing access outside working directory" width="480" height="587"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Outside the sandbox, Claude Code cannot execute Edit, Read, or Bash commands like &lt;code&gt;rm&lt;/code&gt; on unauthorized paths. Combine Sandbox with the permissions settings from Day 12 for comprehensive protection.&lt;/p&gt;

&lt;p&gt;Additional safeguards like PreToolUse Hooks can intercept and block commands before execution. Layer multiple defenses for robust protection against accidental file operations.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/oikon48/status/1999798453006631176" rel="noopener noreferrer"&gt;Original X post&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 14: Hooks for Sensitive Data Filtering
&lt;/h2&gt;

&lt;p&gt;Claude Hooks trigger scripts at specific lifecycle events. Use &lt;code&gt;UserPromptSubmit&lt;/code&gt; and &lt;code&gt;PreToolUse&lt;/code&gt; hooks to filter sensitive information before it reaches the AI agent.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg70siphnd62ar90p6hmt.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg70siphnd62ar90p6hmt.gif" alt="Hooks filtering sensitive information" width="320" height="307"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Create a hook that scans for API keys, credentials, or other sensitive patterns in prompts and file contents. Block execution when sensitive data is detected.&lt;/p&gt;

&lt;p&gt;Beyond blocking, &lt;code&gt;UserPromptSubmit&lt;/code&gt; hooks can append additional context to prompts. Hooks enable powerful automation while maintaining security boundaries.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/oikon48/status/2000164839503917319" rel="noopener noreferrer"&gt;Original X post&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 15: Hooks for Code Formatting
&lt;/h2&gt;

&lt;p&gt;Use &lt;code&gt;PostToolUse&lt;/code&gt; hooks to run formatters automatically after Claude Code edits files.&lt;/p&gt;

&lt;p&gt;Configure in settings.json:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"hooks"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"PostToolUse"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"command"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"prettier --write $CLAUDE_FILE_PATH"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key advantage of Hooks is deterministic behavior outside Claude's context. Formatting always executes correctly without consuming context or relying on the AI to remember to format. This pattern works for linters, type checkers, and other code quality tools.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG8NAMQ1b0AARnWR%3Fformat%3Djpg%26name%3Dmedium" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG8NAMQ1b0AARnWR%3Fformat%3Djpg%26name%3Dmedium" alt="Day 15: Hooks for Code Formatting" width="1200" height="837"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/oikon48/status/2000522222319133071" rel="noopener noreferrer"&gt;Original X post&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 16: External Editor with Ctrl + G
&lt;/h2&gt;

&lt;p&gt;Press &lt;code&gt;Ctrl + G&lt;/code&gt; to open prompts or Plan mode documents in your preferred external editor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fksqtsb2icr4wi7z6i9mi.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fksqtsb2icr4wi7z6i9mi.gif" alt="Opening external editor with Ctrl+G" width="480" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Configure your editor using environment variables:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;VISUAL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"vim"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;VISUAL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"emacs"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;VISUAL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"code --wait"&lt;/span&gt;
&lt;span class="nb"&gt;export &lt;/span&gt;&lt;span class="nv"&gt;VISUAL&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;"cursor --wait"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude Code checks &lt;code&gt;VISUAL&lt;/code&gt; first, then falls back to &lt;code&gt;EDITOR&lt;/code&gt;. This is especially useful for composing complex multi-line prompts or editing detailed plans.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/oikon48/status/2000884610591281582" rel="noopener noreferrer"&gt;Original X post&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 17: Plan Mode
&lt;/h2&gt;

&lt;p&gt;Press &lt;code&gt;Shift + Tab&lt;/code&gt; to switch to Plan mode. Claude creates a planning document that you can review and edit before execution.&lt;/p&gt;

&lt;p&gt;Plan documents are now saved to &lt;code&gt;~/.claude/plans/&lt;/code&gt;, a change introduced around v2.0.34. You can review past plans and track how approaches evolved over time.&lt;/p&gt;

&lt;p&gt;Currently, you cannot specify a custom path for plan documents, though &lt;a href="https://github.com/anthropics/claude-code/issues/12619" rel="noopener noreferrer"&gt;this feature request&lt;/a&gt; exists. Combine Plan mode with &lt;code&gt;Ctrl + G&lt;/code&gt; (Day 16) to edit plans in your preferred editor.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG8WToHQaQAAJB8D%3Fformat%3Djpg%26name%3Dmedium" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG8WToHQaQAAJB8D%3Fformat%3Djpg%26name%3Dmedium" alt="Day 17: Plan Mode" width="1200" height="970"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/oikon48/status/2001247249955733715" rel="noopener noreferrer"&gt;Original X post&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 18: GIF Creation with Claude in Chrome
&lt;/h2&gt;

&lt;p&gt;Version 2.0.72 introduced Claude in Chrome integration. Configure it with the &lt;code&gt;/chrome&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkwgr14gxwuhmtpgtygdw.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkwgr14gxwuhmtpgtygdw.gif" alt="Claude in Chrome creating GIF recordings" width="280" height="206"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Claude in Chrome includes a GIF recording feature that captures browser automation sessions. Record your web application interactions and export them as animated GIFs, useful for creating quick tutorials or documenting workflows.&lt;/p&gt;

&lt;p&gt;While Chrome DevTools MCP provides similar capabilities, Claude in Chrome leverages your browser's user profile, making authenticated interactions easier. The integration enables direct Chrome control via MCP tools from Claude Code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/oikon48/status/2001609660521156620" rel="noopener noreferrer"&gt;Original X post&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 19: Agent Skills Best Practices
&lt;/h2&gt;

&lt;p&gt;Agent Skills became an open standard, now usable in Cursor, GitHub Copilot, and other AI coding assistants. When creating Skills, follow the &lt;a href="https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices" rel="noopener noreferrer"&gt;official best practices&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Keep SKILL.md under 500 lines&lt;/li&gt;
&lt;li&gt;Include specific, concrete examples&lt;/li&gt;
&lt;li&gt;Limit file references to one directory level deep&lt;/li&gt;
&lt;li&gt;Use progressive disclosure for complex information&lt;/li&gt;
&lt;li&gt;Define clear workflow steps&lt;/li&gt;
&lt;li&gt;Leverage scripts for deterministic operations&lt;/li&gt;
&lt;li&gt;Avoid Windows-style paths&lt;/li&gt;
&lt;li&gt;Build in verification and feedback loops&lt;/li&gt;
&lt;li&gt;Include at least three evaluation scenarios&lt;/li&gt;
&lt;li&gt;Test across multiple models&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Start with Skill Creator (Day 8) for a quick prototype, then refine against these best practices. The &lt;a href="https://agentskills.io/home" rel="noopener noreferrer"&gt;Agent Skills registry&lt;/a&gt; provides examples to study.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG8hkTY3bkAArhH8%3Fformat%3Djpg%26name%3Dmedium" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG8hkTY3bkAArhH8%3Fformat%3Djpg%26name%3Dmedium" alt="Day 19: Agent Skills Best Practices" width="991" height="1199"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/oikon48/status/2001973851874570355" rel="noopener noreferrer"&gt;Original X post&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 20: Auto-compact Buffer Size
&lt;/h2&gt;

&lt;p&gt;When auto-compact is enabled, Claude Code reserves a buffer for conversation compression. This Auto-compact Buffer varies based on &lt;code&gt;CLAUDE_CODE_MAX_OUTPUT_TOKENS&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The default buffer is 32k tokens, consuming 22.5% of a 200k context window. Setting max output tokens to 64k (the maximum) increases the buffer to nearly 40% of available context.&lt;/p&gt;

&lt;p&gt;If you have set &lt;code&gt;CLAUDE_CODE_MAX_OUTPUT_TOKENS&lt;/code&gt; without considering this trade-off, revisit your configuration. Maximizing output tokens significantly reduces available context for code and conversation.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG8iSCiFakAIKeBS%3Fformat%3Djpg%26name%3Dmedium" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG8iSCiFakAIKeBS%3Fformat%3Djpg%26name%3Dmedium" alt="Day 20: Auto-compact Buffer Size" width="1070" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/oikon48/status/2002334161814573399" rel="noopener noreferrer"&gt;Original X post&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 21: Async Subagents
&lt;/h2&gt;

&lt;p&gt;Subagents can execute asynchronously in the background. When an async task completes, the main agent receives a notification.&lt;/p&gt;

&lt;p&gt;Practical applications for async Subagents include parallel codebase exploration, concurrent code reviews, and simultaneous search operations across multiple sources.&lt;/p&gt;

&lt;p&gt;Version 2.0.60 introduced this capability. While related tasks may still occasionally wait for Subagent completion, the workflow is substantially improved from earlier versions.&lt;/p&gt;

&lt;p&gt;Anthropic engineers mentioned plans to enhance Swarming (orchestrated multi-agent execution) in 2026. Familiarizing yourself with parallel execution patterns now will prepare you for these capabilities.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG8sCbz9bIAArmAd%3Fformat%3Djpg%26name%3Dmedium" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG8sCbz9bIAArmAd%3Fformat%3Djpg%26name%3Dmedium" alt="Day 21: Async Subagents" width="1197" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/oikon48/status/2002703847291236753" rel="noopener noreferrer"&gt;Original X post&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 22: Code Action + Agent Skills
&lt;/h2&gt;

&lt;p&gt;Claude Code Action runs Claude Code in GitHub Actions on Ubuntu runners. When your repository contains Skills in &lt;code&gt;.claude/skills/&lt;/code&gt;, they are available during Action execution.&lt;/p&gt;

&lt;p&gt;Required setup:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Create Skills in &lt;code&gt;.claude/skills/&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Add "Skill" to &lt;code&gt;claude_args: --allowed-tools&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Use &lt;code&gt;/install-github-app&lt;/code&gt; to configure &lt;code&gt;CLAUDE_CODE_OAUTH_TOKEN&lt;/code&gt; automatically&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Claude Code Action has existed for some time, but Skills integration enables more sophisticated automated workflows. Combined with the upcoming &lt;a href="https://github.blog/changelog/2025-12-16-coming-soon-simpler-pricing-and-a-better-experience-for-github-actions/" rel="noopener noreferrer"&gt;GitHub Actions pricing changes&lt;/a&gt; that reduce GitHub-hosted runner costs, this feature becomes increasingly attractive.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG8xbiP4aMAAGAjd%3Fformat%3Djpg%26name%3Dmedium" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG8xbiP4aMAAGAjd%3Fformat%3Djpg%26name%3Dmedium" alt="Day 22: Code Action + Agent Skills" width="1200" height="906"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/oikon48/status/2003076804769464433" rel="noopener noreferrer"&gt;Original X post&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 23: Parallel Execution
&lt;/h2&gt;

&lt;p&gt;Two primary approaches enable parallel Claude Code execution.&lt;/p&gt;

&lt;p&gt;Same-branch parallelism uses Subagents for concurrent tasks. This works well for read-only operations like code reviews, or when working on components with clear boundaries. Invoke multiple Subagents from Skills for structured parallel workflows.&lt;/p&gt;

&lt;p&gt;Different-branch parallelism uses git worktree to create separate working directories. Run independent Claude Code instances in each worktree for parallel feature development or implementation comparisons. Combine with tmux for orchestrating multiple Claude Code sessions from a single interface.&lt;/p&gt;

&lt;p&gt;At a recent Claude Code Meetup in Tokyo, Anthropic engineers confirmed that Swarming capabilities will receive significant attention in 2026. Early adoption of parallel execution patterns positions you well for these enhancements.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG82q22DagAUQtOx%3Fformat%3Djpg%26name%3Dmedium" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG82q22DagAUQtOx%3Fformat%3Djpg%26name%3Dmedium" alt="Day 23: Parallel Execution" width="1200" height="937"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/oikon48/status/2003445380370042959" rel="noopener noreferrer"&gt;Original X post&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Day 24: Claude Code Ecosystem
&lt;/h2&gt;

&lt;p&gt;Looking back at 2025, the Claude Code ecosystem expanded remarkably from its February 24 launch. In just ten months, the platform grew from a CLI tool to a comprehensive development environment.&lt;/p&gt;

&lt;p&gt;The ecosystem now includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Claude Code CLI and SDK for programmatic integration&lt;/li&gt;
&lt;li&gt;IDE extensions for VSCode, JetBrains, and VSCode forks&lt;/li&gt;
&lt;li&gt;Claude Code on the Web with remote sandbox execution&lt;/li&gt;
&lt;li&gt;Mobile app, desktop, and Slack integration for task submission&lt;/li&gt;
&lt;li&gt;Chrome extension for browser automation&lt;/li&gt;
&lt;li&gt;GitHub Actions integration for CI/CD workflows&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tasks flow seamlessly between these components. Start work on your phone, continue on the Web, finish locally, and deploy through GitHub Actions. The 2026 ecosystem will likely be even more interconnected.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG87ZmcZbgAApatV%3Fformat%3Djpg%26name%3Dmedium" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fpbs.twimg.com%2Fmedia%2FG87ZmcZbgAApatV%3Fformat%3Djpg%26name%3Dmedium" alt="Day 24: Claude Code Ecosystem" width="951" height="1200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://x.com/oikon48/status/2003783713465745652" rel="noopener noreferrer"&gt;Original X post&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;p&gt;Safety and security require proactive configuration. Set up &lt;code&gt;permissions.deny&lt;/code&gt;, enable Sandbox, and use Hooks to filter sensitive data before an accident occurs.&lt;/p&gt;

&lt;p&gt;Context management determines effectiveness. Monitor MCP tool overhead with &lt;code&gt;/context&lt;/code&gt;, understand Auto-compact buffer trade-offs, and remove unused tools.&lt;/p&gt;

&lt;p&gt;Extended thinking requires the right keyword. Only &lt;code&gt;ultrathink&lt;/code&gt; works. Previous keywords like &lt;code&gt;think hard&lt;/code&gt; have been disabled since v2.0.0.&lt;/p&gt;

&lt;p&gt;Skills and Subagents work best together. Use YAML frontmatter to load Skills into Subagents for specialized workflows.&lt;/p&gt;

&lt;p&gt;Parallel execution multiplies productivity. Async Subagents and git worktree enable concurrent work patterns that will become even more powerful with future Swarming capabilities.&lt;/p&gt;

&lt;p&gt;The ecosystem rewards exploration. Features like statusline, external editor integration, and Plan mode document saving improve daily workflows significantly once discovered.&lt;/p&gt;




&lt;p&gt;If you found these tips valuable, follow the author on &lt;a href="https://x.com/oikon48" rel="noopener noreferrer"&gt;X (@oikon48)&lt;/a&gt; for ongoing Claude Code insights and updates.&lt;/p&gt;




&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anthropics/claude-code/tree/main/plugins/claude-opus-4-5-migration" rel="noopener noreferrer"&gt;Opus 4.5 Migration Plugin&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anthropics/claude-code/issues/6235" rel="noopener noreferrer"&gt;AGENTS.md Support Discussion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://code.claude.com/docs/en/claude-code-on-the-web" rel="noopener noreferrer"&gt;Claude Code on the Web Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://code.claude.com/docs/en/sub-agents#file-format" rel="noopener noreferrer"&gt;Subagent File Format&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.reddit.com/r/ClaudeAI/comments/1pgxckk/claude_cli_deleted_my_entire_home_directory_wiped/" rel="noopener noreferrer"&gt;rm -rf Incident on Reddit&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anthropics/claude-code/issues/12619" rel="noopener noreferrer"&gt;Plan Document Path Feature Request&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices" rel="noopener noreferrer"&gt;Agent Skills Best Practices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.blog/changelog/2025-12-16-coming-soon-simpler-pricing-and-a-better-experience-for-github-actions/" rel="noopener noreferrer"&gt;GitHub Actions Pricing Changes&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>claudecode</category>
      <category>ai</category>
      <category>productivity</category>
      <category>development</category>
    </item>
    <item>
      <title>Can AI Tools Implement Designs Perfectly?</title>
      <dc:creator>Oikon</dc:creator>
      <pubDate>Sun, 12 Oct 2025 05:52:28 +0000</pubDate>
      <link>https://dev.to/oikon/can-ai-tools-implement-designs-perfectly-h36</link>
      <guid>https://dev.to/oikon/can-ai-tools-implement-designs-perfectly-h36</guid>
      <description>&lt;p&gt;AI tools promise to close the gap between design and implementation, but &lt;strong&gt;how close do they actually get?&lt;/strong&gt; I decided to put three popular approaches to the test with the same Figma design.&lt;/p&gt;

&lt;p&gt;The results revealed not just differences in output quality, but fundamentally different philosophies about how design-to-code translation should work. What I found challenges some common assumptions about &lt;strong&gt;pixel-perfect implementation and suggests a more nuanced view of what “perfectly” really means&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flae82tqp0k0ft24kz0wl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flae82tqp0k0ft24kz0wl.png" alt="Figma to Code" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Kombai&lt;/strong&gt; achieved the highest design fidelity at 75–80% with Material UI components and real image handling&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Codex CLI&lt;/strong&gt; excelled at semantic HTML and accessibility with proper aria attributes and document structure&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Claude Code&lt;/strong&gt; delivered thoughtful component architecture with 13 independent, well-organized components&lt;/li&gt;
&lt;li&gt;Figma MCP enables AI agents to read design structure directly, while specialized tools like Kombai optimize specifically for frontend generation &lt;strong&gt;The Current State of AI-Driven Design Implementation&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI tools have become remarkably capable at backend implementation, yet &lt;strong&gt;frontend development presents unique challenges that remain partially unsolved&lt;/strong&gt;. After working extensively with various AI coding assistants, I’ve identified four persistent challenges in translating designs to code.&lt;/p&gt;

&lt;p&gt;Reproduction accuracy stands as the most visible issue. Capturing design intent in code requires understanding not just what elements appear on screen, but why they’re arranged that way. AI-generated interfaces often carry a certain recognizable aesthetic that experienced designers immediately spot.&lt;/p&gt;

&lt;h3&gt;
  
  
  Implementation gaps
&lt;/h3&gt;

&lt;p&gt;Implementation gaps frequently surface around responsive design. Unless explicitly instructed, AI tools tend to create fixed layouts that break on different screen sizes. This happens even when the underlying framework fully supports responsive patterns.&lt;/p&gt;

&lt;h3&gt;
  
  
  Knowledge currency
&lt;/h3&gt;

&lt;p&gt;Knowledge currency affects output quality in ways that aren’t always obvious. The latest libraries and frameworks evolve faster than training data, leading to outdated patterns or missed opportunities to use newer, better approaches.&lt;/p&gt;

&lt;h3&gt;
  
  
  Maintainability concerns
&lt;/h3&gt;

&lt;p&gt;Maintainability concerns emerge most clearly in component design. Consistent, reusable component structures require architectural thinking that goes beyond making individual screens look correct. Without careful prompting, generated code often mixes abstraction levels or duplicates logic across components.&lt;/p&gt;

&lt;p&gt;Even with experienced designers and engineers involved, achieving satisfying UI/UX completeness through AI assistance alone remains difficult. &lt;strong&gt;The common critique that outputs aren’t “pixel-perfect” misses a more nuanced point: pixel-perfect may not always be the goal, but intentional fidelity to design decisions absolutely is&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpb3qdwo960wklrkqgb66.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpb3qdwo960wklrkqgb66.png" alt="Figma" width="300" height="168"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The most promising current approach for faithful design reproduction involves using Figma as the source of truth and generating code from that structured design data&lt;/strong&gt;. This works because Figma files contain component hierarchies and relationships that remain invisible in screenshots or mockups. AI tools can parse this structure in ways they simply cannot with image-based inputs.&lt;/p&gt;

&lt;h2&gt;
  
  
  Methods for Figma to Code
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Understanding Figma MCP
&lt;/h3&gt;

&lt;p&gt;Figma MCP represents a bridge technology that allows AI agents to directly read and interpret Figma design data. Rather than describing a design through images or specifications, MCP enables the AI to access the actual design file structure, including layers, components, constraints, and properties.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmz2e77dzoa557eduik26.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmz2e77dzoa557eduik26.png" alt="Figma MCP" width="800" height="1005"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Setting up Figma MCP requires Figma Desktop, which provides a local MCP server that AI tools can connect to. The process starts in Figma Desktop’s preferences, where enabling the &lt;strong&gt;“Enable desktop MCP server”&lt;/strong&gt; option activates the local server on your machine.&lt;/p&gt;

&lt;p&gt;Once the Figma side is configured, AI CLI tools need configuration to connect to that server. The exact format varies by tool, but the principle remains consistent: point the AI tool to the local MCP endpoint that Figma Desktop provides.&lt;/p&gt;

&lt;p&gt;For Claude Code, configuration lives in &lt;code&gt;~/.claude.json&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"mcpServers"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"figma-mcp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
      &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"http://127.0.0.1:3845/mcp"&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For Codex CLI, configuration lives in &lt;code&gt;~/.codex/config.toml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[mcp_servers.figma]&lt;/span&gt;
&lt;span class="py"&gt;command&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"npx"&lt;/span&gt;
&lt;span class="py"&gt;args&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"-y"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"mcp-remote"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"http://127.0.0.1:3845/mcp"&lt;/span&gt; &lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key advantage of MCP over image-based approaches becomes clear when the AI needs to understand component relationships. A button nested inside a card component within a layout grid carries structural meaning that images alone cannot convey. &lt;strong&gt;MCP exposes this hierarchy directly&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Specialized Frontend AI Tools
&lt;/h3&gt;

&lt;p&gt;While Figma MCP enables general-purpose AI tools to work with design files, another category of tools focuses specifically on frontend code generation. Several options exist in this space, including:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Locofy.ai&lt;/li&gt;
&lt;li&gt;Anima&lt;/li&gt;
&lt;li&gt;Builder.io&lt;/li&gt;
&lt;li&gt;Kombai.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj5wm6hum8kie1t4hegxc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj5wm6hum8kie1t4hegxc.png" alt="Kombai" width="800" height="433"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kombai caught my attention for its distinct approach to the problem.&lt;/strong&gt; Developed by an Indian startup, Kombai launched officially in August 2025 after gaining significant traction on Product Hunt. The tool’s architecture makes several opinionated choices about how design-to-code translation should work.&lt;/p&gt;

&lt;p&gt;Rather than operating within the command line, Kombai functions as an IDE extension available for VSCode, Cursor, Windsurf, and Trae. This integration allows Kombai to analyze entire project contexts, understanding existing code patterns, dependencies, and architectural decisions.&lt;/p&gt;

&lt;p&gt;The tool’s workflow differs notably from MCP-based approaches. Kombai executes code changes in a virtual environment first, allowing developers to review and test before accepting changes into their local codebase. This preview-then-accept pattern reduces the risk of breaking existing functionality.&lt;/p&gt;

&lt;p&gt;Technology stack configuration represents another distinguishing feature. Developers can specify their preferred frameworks and libraries upfront, and &lt;strong&gt;Kombai generates code matching those choices rather than defaulting to a single tech stack&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Project-wide analysis sets Kombai apart from simpler screenshot-to-code tools. By understanding the broader codebase, Kombai can generate components that match existing patterns and integrate with established architecture rather than creating isolated, inconsistent code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparing 3 AI tools
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frh6olg7009gow8r24olr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frh6olg7009gow8r24olr.png" alt="Sample Figma template" width="800" height="502"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;To compare these approaches fairly, I used an identical Figma design across all three tools. The design came from Figma Community: a portfolio website template with multiple sections, typography hierarchy, images, and interactive elements. This provided enough complexity to reveal meaningful differences between tools.&lt;/p&gt;

&lt;p&gt;Figma template: &lt;a href="https://www.figma.com/community/file/1170206889562959306" rel="noopener noreferrer"&gt;https://www.figma.com/community/file/1170206889562959306&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The testing methodology kept variables controlled. Each tool received the same input: a Figma design URL pointing to a specific frame. The prompt remained consistent across all tests:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;FIGMA_DESIGN_URL Implement this Figma design
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Obtaining the Figma URL requires using Figma’s “Copy/Paste as” menu and selecting “Copy link to selection.” This generates a URL that references a specific frame or component within the design file, which the AI tools can then retrieve through Figma’s API or MCP connection.&lt;/p&gt;

&lt;p&gt;The evaluation focused on several dimensions: &lt;strong&gt;design fidelity measured visually against the original, component architecture examining how code was structured, responsive behavior testing across viewport sizes, and implementation quality looking at semantic HTML, accessibility, and maintainability patterns&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Claude Code with Figma MCP
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1c46ej1mumzuc20o6gy1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1c46ej1mumzuc20o6gy1.png" alt="Claude Code + Figma MCP" width="800" height="506"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Claude Code, powered by Sonnet 4.5, generated an implementation centered around Next.js 14 with App Router. The output consisted of 13 independent components, each representing a distinct section or functional element of the design.&lt;/p&gt;

&lt;p&gt;The technical stack reflected modern React patterns:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Next.js 14 with App Router for routing and server components&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TailwindCSS 3.4 for styling with utility classes&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TypeScript for type safety and developer experience&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Component organization showed thoughtful separation of concerns. Each major section of the portfolio received its own component file: Hero, About, Projects, Skills, Contact, and so on. This modularity would make future maintenance and updates more manageable.&lt;/p&gt;

&lt;p&gt;Design fidelity reached approximately 65–70%, with particular success in replicating gradient backgrounds and blur effects. These subtle visual details often get lost in simpler implementations, so seeing them preserved indicated Claude’s attention to the complete visual hierarchy.&lt;/p&gt;

&lt;p&gt;Typography implementation captured the design’s intent reasonably well. Heading sizes, font weights, and text spacing matched the Figma specifications closely, though some fine-tuning of line heights would improve the final polish.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The most significant limitation appeared in responsive design.&lt;/strong&gt; While the implementation used some responsive patterns, several components relied on fixed pixel values that broke layouts on smaller screens. This partially responsive approach suggests the AI interpreted the desktop design literally rather than inferring adaptive behavior.&lt;/p&gt;

&lt;p&gt;Image handling defaulted to placeholders, requiring manual replacement with actual assets. This makes sense given the AI cannot access project-specific images, but it does add a post-generation step to the workflow.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Overall, Claude Code with Figma MCP delivered a solid foundation that would require moderate refinement for production use. The component architecture particularly stood out as a strength, providing good starting structure for continued development.&lt;/strong&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Codex CLI with Figma MCP
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr620rn0kbnxqzw0rfu86.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fr620rn0kbnxqzw0rfu86.png" alt="Codex CLI + Figma MCP" width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Codex CLI took a notably different architectural approach, generating both Next.js components and pure HTML files. This hybrid strategy reflected an interesting interpretation of how to structure the implementation.&lt;/p&gt;

&lt;p&gt;The technical stack combined modern frameworks with traditional web approaches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Next.js 14 with App Router serving as the primary framework&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Custom CSS using BEM-style naming conventions rather than utility classes&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TypeScript for the React components&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Semantic HTML with proper document structure in pure HTML sections&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Semantic HTML usage stood out as the implementation’s strongest characteristic. The code extensively used appropriate HTML5 elements: &lt;code&gt;&amp;lt;dl&amp;gt;\&lt;/code&gt;, &lt;code&gt;&amp;lt;dt&amp;gt;\&lt;/code&gt;, and &lt;code&gt;&amp;lt;dd&amp;gt;\&lt;/code&gt; tags for definition lists, &lt;code&gt;&amp;lt;article&amp;gt;\&lt;/code&gt; for content sections, &lt;code&gt;&amp;lt;nav&amp;gt;\&lt;/code&gt; for navigation, and proper heading hierarchy throughout. This attention to document semantics improves accessibility and SEO significantly.&lt;/p&gt;

&lt;p&gt;Accessibility received explicit attention through aria attributes. Interactive elements included &lt;code&gt;aria-label\&lt;/code&gt; properties, navigation sections contained &lt;code&gt;aria-current\&lt;/code&gt; indicators, and the overall structure supported screen reader navigation effectively.&lt;/p&gt;

&lt;p&gt;Responsive design implementation outperformed the Claude Code version. The CSS included media queries at appropriate breakpoints, and layouts adapted reasonably well across device sizes. This suggested Codex either inferred responsive requirements or defaulted to responsive patterns.&lt;/p&gt;

&lt;p&gt;Design fidelity measured around 70–75%, slightly higher than Claude Code’s output. The combination of semantic structure and careful CSS resulted in an implementation that captured both visual appearance and underlying document meaning.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The mixed architecture of React components plus standalone HTML felt somewhat inconsistent&lt;/strong&gt;. In a real project, consolidating to a single approach would likely improve maintainability. However, the semantic HTML quality demonstrated that Codex CLI understands document structure at a deeper level than purely presentational frameworks might suggest.&lt;/p&gt;

&lt;p&gt;Image placeholders appeared here as well, maintaining consistency with the Claude Code behavior. This remains an unavoidable limitation when AI tools cannot access actual project assets.&lt;/p&gt;

&lt;h3&gt;
  
  
  Kombai
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpazxs2l6emgoyyeeb3ka.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpazxs2l6emgoyyeeb3ka.png" alt="Kombai" width="800" height="507"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kombai’s implementation differed fundamentally from the MCP-based approaches, reflecting its specialization in frontend generation.&lt;/strong&gt; The output leveraged Material UI extensively, using that component library’s established patterns throughout.&lt;/p&gt;

&lt;p&gt;The technical stack centered on React with specific tooling choices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;React 18 with Vite for fast development and optimized builds&lt;/li&gt;
&lt;li&gt;Material UI (MUI) version 5 providing comprehensive component primitives&lt;/li&gt;
&lt;li&gt;TypeScript for type safety&lt;/li&gt;
&lt;li&gt;Emotion for CSS-in-JS styling integrated with MUI’s theming&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Design fidelity reached 75–80%, the highest among the three tools tested. This superior reproduction quality came partly from MUI’s polished components but also from Kombai’s optimization specifically for this task. Visual details like spacing, typography, and color matched the Figma design more precisely than either MCP-based approach.&lt;/p&gt;

&lt;p&gt;Most strikingly, &lt;strong&gt;Kombai included actual profile images from the Figma file rather than placeholders.&lt;/strong&gt; This asset handling demonstrated deeper integration with Figma’s resources and reduced post-generation work significantly.&lt;/p&gt;

&lt;p&gt;Responsive implementation used MUI’s breakpoint system throughout. This declarative approach to responsive design resulted in layouts that adapted smoothly across viewport sizes. The code explicitly defined behavior at different breakpoints using MUI’s &lt;code&gt;sx\&lt;/code&gt; prop and theme breakpoint utilities. Component organization followed a more functional pattern than the MCP approaches. Rather than breaking the design into 13 small components, Kombai created 9 larger sections plus shared utility components. This reflected a different architectural philosophy focused on page sections rather than granular component decomposition.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The primary tradeoff came from Material UI dependency.&lt;/strong&gt; Projects already using MUI would integrate this code seamlessly, but teams using other design systems or preferring unstyled components would face significant adaptation work. The implementation locked in not just component structure but an entire ecosystem of styling and theming.&lt;/p&gt;

&lt;p&gt;Despite this constraint, Kombai’s output required less refinement to reach production quality. The combination of high visual fidelity, proper responsive design, and working asset integration meant fewer gaps to fill after generation.&lt;/p&gt;

&lt;h3&gt;
  
  
  3 AI tools analysis
&lt;/h3&gt;

&lt;p&gt;Examining the three implementations side by side reveals distinct strengths and appropriate use cases for each approach.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcdglsq98ldym627u6enm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcdglsq98ldym627u6enm.png" alt="Table of analysis" width="800" height="285"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Claude Code’s strength lies in component architecture thinking. The 13-component breakdown creates a maintainable structure that teams can extend incrementally. This matters more as projects grow and multiple developers contribute to the codebase. Codex CLI distinguished itself through semantic HTML and accessibility focus. Projects where SEO, screen reader support, or standards compliance are priorities would benefit most from this approach. The attention to document structure suggests a deeper understanding of web fundamentals. Kombai optimized for visual fidelity and development speed. Getting 75–80% reproduction accuracy reduces designer feedback cycles significantly. For projects using Material UI or willing to adopt it, Kombai delivers the most complete starting point.&lt;/p&gt;

&lt;p&gt;Technology stack preferences heavily influence which tool fits best. Teams standardized on TailwindCSS would prefer Claude Code’s output. Projects prioritizing semantic HTML and custom CSS would lean toward Codex CLI. Material UI shops would find Kombai’s code immediately usable.&lt;/p&gt;

&lt;p&gt;The responsive design gap in Claude Code’s output represents a correctable limitation. Adding appropriate responsive patterns to the generated code requires work but builds on a solid component foundation. In contrast, rearchitecting Kombai’s code away from Material UI would require more fundamental changes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Takeaways and Practical Implications
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fixkvwsbyyx6whxypyitc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fixkvwsbyyx6whxypyitc.png" alt="Key takeaways" width="800" height="418"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This testing revealed that “faithful implementation” means different things depending on what you value. Pure visual matching, semantic structure, component architecture, and technology alignment all represent valid but distinct goals.&lt;/p&gt;

&lt;p&gt;Current AI tools achieve 65–80% design fidelity without human intervention. This falls short of pixel-perfect reproduction but provides substantial value as a starting point. The remaining 20–35% typically involves refinement rather than fundamental rework. Framework and library consistency matters more than many developers initially expect. Generated code must fit into existing project structure, dependencies, and patterns. A beautiful standalone implementation that doesn’t match your tech stack creates integration work that reduces the time savings.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Engineer evaluation and adjustment remains necessary at this stage of AI capability.&lt;/strong&gt; Reviewing generated code for responsive behavior, accessibility, semantic correctness, and architectural fit represents unavoidable steps. Treating AI output as a first draft rather than final code sets appropriate expectations.&lt;/p&gt;

&lt;p&gt;The specialization versus generalization tradeoff manifests clearly in these results. Kombai’s frontend-specific optimization produces better immediate output for its narrow domain. Claude Code and Codex CLI offer more flexibility but require better prompting to achieve similar quality.&lt;/p&gt;

&lt;p&gt;For simple implementations and prototypes, current tools deliver sufficient quality for many use cases. Moving from design to working demo in minutes rather than hours changes project workflows substantially. &lt;strong&gt;The draft generated becomes a conversation starter that designers and engineers refine collaboratively.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow me on X
&lt;/h2&gt;

&lt;p&gt;I also post on X (Twitter) about development tools, AI experiments, and frontend techniques:&lt;/p&gt;

&lt;p&gt;X → &lt;a href="https://x.com/oikon48" rel="noopener noreferrer"&gt;https://x.com/oikon48&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;Claude Code: &lt;a href="https://claude.ai/code" rel="noopener noreferrer"&gt;https://claude.ai/code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Codex CLI: &lt;a href="https://github.com/openai/codex-cli" rel="noopener noreferrer"&gt;https://github.com/openai/codex-cli&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kombai: &lt;a href="https://kombai.com/" rel="noopener noreferrer"&gt;https://kombai.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Figma Community Portfolio Design: &lt;a href="https://www.figma.com/community/file/1170206889562959306" rel="noopener noreferrer"&gt;https://www.figma.com/community/file/1170206889562959306&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>claude</category>
      <category>codex</category>
      <category>webdev</category>
    </item>
    <item>
      <title>nano-banana special prompt achieved rapid Mobile UI Mockups</title>
      <dc:creator>Oikon</dc:creator>
      <pubDate>Sun, 14 Sep 2025 05:14:40 +0000</pubDate>
      <link>https://dev.to/oikon/nano-banana-special-prompt-achieved-rapid-mobile-ui-mockups-1mif</link>
      <guid>https://dev.to/oikon/nano-banana-special-prompt-achieved-rapid-mobile-ui-mockups-1mif</guid>
      <description>&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx31l6b3dqslkl9fp28ci.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx31l6b3dqslkl9fp28ci.png" alt="iosapp-uimockup" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use Gemini 2.5 Flash Image (a.k.a "nano-banana") to generate a single figure with exactly four iPhone screens showing a left‑to‑right user journey&lt;/strong&gt;. A copy‑paste prompt blueprint is included below, along with three ready‑made customizations (Fitness, Cooking, Finance). Iterate lightly by adjusting theme, contrast, and density, keeping backgrounds minimal, and labeling each screen.&lt;/p&gt;

&lt;p&gt;I recently dove into mobile app development and quickly ran into a familiar early-stage hurdle: turning fuzzy ideas into concrete UI directions. Traditional approaches like paper sketches, wireframes, or Figma all work well, but each comes with a learning curve and setup time. For quick ideation on layout, flow, and visual tone, without opening a design tool, &lt;strong&gt;Google’s Gemini 2.5 Flash Image (a.k.a “nano-banana”) is a surprisingly capable partner&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In this article, &lt;strong&gt;I’ll share a prompt-first workflow for generating high-quality, consistent, four-screen iOS mockups that communicate a complete user journey&lt;/strong&gt;. You’ll get a copy‑paste prompt blueprint you can reuse, three ready‑made customizations (Fitness, Cooking, Personal Finance), and practical tips to tune outputs while avoiding common pitfalls.&lt;/p&gt;

&lt;p&gt;This isn’t a replacement for proper product design. &lt;strong&gt;It’s a fast, visual way to explore directions, align with stakeholders, and then hand off to Figma or code with more confidence&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is “nano-banana”?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://x.com/OfficialLoganK/status/1960343135436906754" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F79rp9j96iye1tjmq335g.png" alt="X post" width="800" height="892"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Gemini 2.5 Flash Image (“nano-banana”) is Google’s image-generation model released in late August 2025. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It’s optimized for speed and consistency&lt;/strong&gt;, and it does especially well with structured prompts that describe layout, device framing, and content constraints.&lt;/p&gt;

&lt;p&gt;You can use nano-banana in Google AI Studio:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://aistudio.google.com/" rel="noopener noreferrer"&gt;https://aistudio.google.com/&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why a prompt-first mockup?
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;A prompt-first approach delivers speed to clarity&lt;/strong&gt;, producing realistic screens in minutes that are ideal for brainstorming and stakeholder conversations. It has low overhead because you can explore concepts without setting up design files or libraries. It also encourages journey‑first thinking by forcing clarity on the flow rather than on isolated screens, and it’s repeatable since a structured prompt makes results consistent and easy to iterate.&lt;/p&gt;

&lt;h2&gt;
  
  
  The 4‑screen mockup prompt blueprint
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fopbae88k0yeyhuj6u897.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fopbae88k0yeyhuj6u897.png" alt="4-screen mockup" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use the following prompt to generate &lt;strong&gt;a single image with four iPhone screens laid out horizontally&lt;/strong&gt;, telling a left‑to‑right user journey. Replace the bracketed fields with your app’s details.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Create a professional iOS app mockup figure&amp;gt;
showing exactly 4 iPhone screens arranged horizontally in a single high-resolution image. The screens demonstrate a complete user journey for a [Application Type] application.

&amp;lt;APP SPECIFIC CUSTOMIZATION&amp;gt;
Application Core: [User Input of application core]
Primary Features:
1. [User Input of feature 1, example: Dashboard]
2. [User Input of feature 2, example: Figure]
3. [User Input of feature 3, example: Charts]
4. [User Input of feature 4, example: Log]
Visual Theme: [User Input of Theme, example: Energetic orange and black theme, bold sans-serif typography, high contrast design, motivational imagery]
Target Audience: [User Input of audience, example: Aged 20-40]
&amp;lt;END CUSTOMIZATION&amp;gt;

DETAILED VISUAL SPECIFICATIONS:
Device Frame: Modern iPhone 15/16 Pro Max with Dynamic Island, edge-to-edge display, no home button
Screen Resolution: High-quality, crisp rendering at 2796×1290 pixels per screen
Background Setting: Subtle blurred gradient or professional studio backdrop that complements the app theme
Lighting: Soft, even lighting with minimal shadows for professional presentation

UI/UX REQUIREMENTS:
Native iOS 17+ components using SwiftUI design language
System font (SF Pro) with proper typography hierarchy
Consistent spacing following Apple's Human Interface Guidelines (8pt grid system)
Interactive elements clearly distinguishable (buttons, toggles, text fields)
Proper safe areas and status bar implementation
Tab bar or navigation structure visible where appropriate
Realistic, meaningful content (no lorem ipsum) - use actual examples relevant to the app
Clear visual flow from left to right showing user progression

COMPOSITION AND STYLE:
Arrange 4 iPhone mockups in a horizontal line with equal spacing
Each screen labeled with its function at the top or bottom
Consistent color palette throughout all screens
Use depth and shadows to create professional mockup appearance
Include subtle animations indicators where relevant (like transition hints)
Show different states (empty states, filled states, active selections)

OUTPUT FORMAT:
Single cohesive figure, resolution minimum, professional presentation quality suitable for App Store submission or investor pitch deck. Photorealistic device rendering with the app screens perfectly integrated.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  How to use it
&lt;/h2&gt;

&lt;p&gt;Define the journey by picking four states that tell a cohesive story (for example, Overview → Details → Edit → Confirm). &lt;strong&gt;Fill the APP SPECIFIC CUSTOMIZATION with concrete, real content—avoid lorem ipsum entirely.&lt;/strong&gt; Generate and assess the result by checking consistency across screens in type, spacing, colors, and data. Iterate with small edits by nudging theme, contrast, or content density and tightening typographic hierarchy. When you have a clear winner, export the figure for your deck, brief, or design kickoff.&lt;/p&gt;

&lt;h2&gt;
  
  
  Three ready‑to‑use customizations
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1) Fitness Tracker
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi237k12dzedhvh56rxzn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi237k12dzedhvh56rxzn.png" alt="Fitness Tracker" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use this block to replace the &lt;code&gt;&amp;lt;APP SPECIFIC CUSTOMIZATION&amp;gt;&lt;/code&gt; section in the blueprint.&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Create a professional iOS app mockup figure&amp;gt;
showing exactly 4 iPhone screens arranged horizontally in a single high-resolution image. The screens demonstrate a complete user journey for a Fitness tracker application.

&amp;lt;APP SPECIFIC CUSTOMIZATION&amp;gt;
Application Core: Personal fitness tracking and workout planning application with AI coaching
Primary Features:
1. Dashboard - Daily activity summary, calories burned, steps, heart rate
2. Workout Library - Exercise videos, custom routines, difficulty levels
3. Progress Charts - Weight trends, strength gains, body measurements over time
4. Activity Log - Workout history, personal records, achievement badges
Visual Theme: Energetic orange and black theme, bold sans-serif typography, high contrast design, motivational imagery with gradient accents
Target Audience: Health-conscious individuals aged 20-40
&amp;lt;END CUSTOMIZATION&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2) Cooking Recipe App
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe3iilx3v1yep5vorcwxn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fe3iilx3v1yep5vorcwxn.png" alt="cooking-recipe-app" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use this block to replace the  section in the blueprint.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Create a professional iOS app mockup figure&amp;gt;
showing exactly 4 iPhone screens arranged horizontally in a single high-resolution image. The screens demonstrate a complete user journey for a Cooking recipe application.

&amp;lt;APP SPECIFIC CUSTOMIZATION&amp;gt;
Application Core: Smart recipe organizer with meal planning and grocery list generation
Primary Features:
1. Recipe Feed - Curated daily recipes with dietary filters and seasonal suggestions
2. Meal Planner - Weekly calendar view with drag-and-drop meal scheduling
3. Shopping List - Auto-generated grocery lists organized by store sections
4. My Cookbook - Personal recipe collection with family recipes and notes
Visual Theme: Warm earth tones with sage green accents, elegant serif headers, food photography backgrounds, minimalist card-based layouts
Target Audience: Home cooks and food enthusiasts aged 25-50
&amp;lt;END CUSTOMIZATION&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3) Personal Finance Manager
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft0koxb9y43ioxtrc5qcu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft0koxb9y43ioxtrc5qcu.png" alt="Personal Finance Manager" width="800" height="800"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Use this block to replace the  section in the blueprint.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;lt;Create a professional iOS app mockup figure&amp;gt;
showing exactly 4 iPhone screens arranged horizontally in a single high-resolution image. The screens demonstrate a complete user journey for a personal finance manager application.

&amp;lt;APP SPECIFIC CUSTOMIZATION&amp;gt;
Application Core: Smart personal finance manager with AI-powered spending insights and investment tracking
Primary Features:
1. Overview - Total balance, monthly spending summary, budget status, upcoming bills
2. Transactions - Categorized expense list with merchant logos, search and filters
3. Analytics - Spending breakdown charts, category trends, savings goals progress
4. Investments - Portfolio performance, stock watchlist, crypto holdings, market news
Visual Theme: Professional navy blue and gold accents, clean geometric patterns, financial data visualizations with glassmorphism effects, trust-inspiring design
Target Audience: Young professionals and investors aged 25-45
&amp;lt;END CUSTOMIZATION&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Quality tips and tuning
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Keep it real&lt;/strong&gt; by replacing placeholders with plausible, domain‑specific content such as dates, names, amounts, and imagery. Enforce hierarchy by asking for a clear typographic hierarchy using SF Pro and by constraining line lengths—for example, keep titles under 30 characters. Increase contrast if results look washed out by specifying high‑contrast, WCAG‑conscious color usage. Tighten spacing by including an 8pt grid and consistent spacing in prompts, and request more negative space if layouts feel crowded. Control density by limiting per‑screen content to six to eight distinct elements. Anchor the journey by explicitly naming each screen in the prompt and requesting labels on the mockups. Iterate lightly, changing one variable at a time—colors, data density, or component style—before regenerating.&lt;/p&gt;

&lt;h3&gt;
  
  
  FAQ
&lt;/h3&gt;

&lt;p&gt;Why four screens? &lt;/p&gt;

&lt;p&gt;Four is enough to show context → explore → focus → commit without overwhelming the viewer, and the format fits neatly in a wide figure for decks. &lt;br&gt;
In addition, Generative AI has less capability to make consistency when generating separate images. &lt;/p&gt;

&lt;h2&gt;
  
  
  When to use nano‑banana vs. a design tool
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Use nano‑banana for early ideation and alignment&lt;/strong&gt; when you need fast, realistic visuals to explore directions, align stakeholders, or kick off discussions without opening Figma or Sketch. It especially shines when you want to present a left‑to‑right user flow (onboarding → browse → detail → act) in one cohesive figure. &lt;/p&gt;

&lt;p&gt;For specs and interactivity, move to Figma/Sketch/XD for component specs, typography tokens, responsiveness, and interactive prototypes, and refer to Apple’s Human Interface Guidelines (HIG) for platform‑correct patterns and accessibility. Treat nano‑banana as a way to visualize, then validate color/contrast and touch targets against WCAG and HIG in your design tool or implementation. In short, generate to decide direction and design to solidify implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Nano-banana shows new way of UI designing&lt;/strong&gt;. Prompt‑first mockups won’t replace design systems, but they’re fantastic for momentum. Use the blueprint to frame a journey, generate credible screens, and then bring the winning direction into Figma or code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Follow on X
&lt;/h2&gt;

&lt;p&gt;I share insights about AI development tools and trends on X:&lt;/p&gt;

&lt;p&gt;X → &lt;a href="https://x.com/oikon48" rel="noopener noreferrer"&gt;https://x.com/oikon48&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;p&gt;Google AI Studio:&lt;br&gt;
&lt;a href="https://aistudio.google.com/" rel="noopener noreferrer"&gt;https://aistudio.google.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Apple Human Interface Guidelines (HIG): &lt;br&gt;
&lt;a href="https://developer.apple.com/design/human-interface-guidelines/" rel="noopener noreferrer"&gt;https://developer.apple.com/design/human-interface-guidelines/&lt;/a&gt;&lt;/p&gt;

</description>
      <category>ai</category>
      <category>nanobanana</category>
      <category>gemini</category>
      <category>uidesign</category>
    </item>
    <item>
      <title>From Figma to Frontend in Minutes: A Hands-On Review of "Kombai"</title>
      <dc:creator>Oikon</dc:creator>
      <pubDate>Sun, 03 Aug 2025 13:44:58 +0000</pubDate>
      <link>https://dev.to/oikon/from-figma-to-frontend-in-minutes-a-hands-on-review-of-kombai-219o</link>
      <guid>https://dev.to/oikon/from-figma-to-frontend-in-minutes-a-hands-on-review-of-kombai-219o</guid>
      <description>&lt;p&gt;Note: this original post is in &lt;a href="https://zenn.dev/oikon/articles/kombai-frontend" rel="noopener noreferrer"&gt;Zenn&lt;/a&gt; (Japansese)&lt;/p&gt;

&lt;p&gt;I'm excited to share my experience with &lt;strong&gt;Kombai&lt;/strong&gt;, an AI-powered frontend tool that specializes in Figma to Code conversion.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--1-iJgl-u--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2F7b2198d5cca12a97cd3f72bf.png%253Fsha%253D482bb1928662da12ffb9b7a3222b824ffde0a628" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--1-iJgl-u--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2F7b2198d5cca12a97cd3f72bf.png%253Fsha%253D482bb1928662da12ffb9b7a3222b824ffde0a628" alt="top" width="1200" height="657"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kombai previously ranked #1 on &lt;a href="https://www.producthunt.com/products/kombai" rel="noopener noreferrer"&gt;Product Hunt&lt;/a&gt; and was officially released on July 31st, 2025.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Overall Assessment
&lt;/h2&gt;

&lt;p&gt;After testing Kombai extensively, here are my key takeaways:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Easy to use as VSCode or Cursor plugin&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Excellent sandbox UI preview functionality&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;High UI compilation success rate&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Not pixel-perfect for Figma to Code, but excellent as a starting point&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AI coding tools like Claude Code often struggle with frontend and UI development, so I find frontend-specialized AI tools particularly interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  About Kombai
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://kombai.com/" rel="noopener noreferrer"&gt;https://kombai.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kombai is an AI agent specializing in frontend development and has gained attention as an AI-powered development assistance tool. In 2023, it was selected as the most upvoted tool on Product Hunt (&lt;a href="https://www.producthunt.com/products/kombai" rel="noopener noreferrer"&gt;link&lt;/a&gt;). Kombai aims to automate frontend development with AI.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;At Kombai are building a developer tool for web app developers which takes away their mundane automatable tasks like writing and maintaining CSS and other boilerplate JS code. Our vision is to automate all the mundane tasks a frontend dev team has to do today, accounting for 60-70% of their work.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The &lt;a href="https://kombai.com/" rel="noopener noreferrer"&gt;product page&lt;/a&gt; showcases benchmarks for frontend development. Kombai reports better performance than commonly used AI coding agents in three areas: Code Review, Feature Implementation, and Compilation Success.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--PBXiS9dt--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2Fe11390240ddbd2ec36ce9f4b.png%253Fsha%253D1e03ffcea1f39f5845ec8f8d5b5d035cb2b4740c" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--PBXiS9dt--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2Fe11390240ddbd2ec36ce9f4b.png%253Fsha%253D1e03ffcea1f39f5845ec8f8d5b5d035cb2b4740c" alt="benchi" width="1200" height="675"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Pricing starts with a free plan that includes credits. As I'll explain later, &lt;strong&gt;loading one Figma design and creating UI typically costs around 20-40 credits&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--JRlemyqK--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2F10c40f99cac1ae571c27ff47.png%253Fsha%253Dbe7ad4c15dcfe2574ce99a5ec563434628585137" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--JRlemyqK--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2F10c40f99cac1ae571c27ff47.png%253Fsha%253Dbe7ad4c15dcfe2574ce99a5ec563434628585137" alt="price" width="1200" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Trying Kombai
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Installation
&lt;/h3&gt;

&lt;p&gt;Kombai is currently available on these marketplaces:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;VSCode&lt;/li&gt;
&lt;li&gt;Cursor&lt;/li&gt;
&lt;li&gt;Windsurf&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I'll explain the process of installing Kombai in Cursor.&lt;/p&gt;

&lt;p&gt;Search for "Kombai" in the plugin search, and you'll see Kombai with a dog icon.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--jAjOdfF6--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2F9407cd71461ed5f15686efa1.png%253Fsha%253Dbdf976dad9b1ee5a6d7507345924ca65305ffaf4" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--jAjOdfF6--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2F9407cd71461ed5f15686efa1.png%253Fsha%253Dbdf976dad9b1ee5a6d7507345924ca65305ffaf4" alt="install" width="1200" height="585"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After installation, a &lt;code&gt;Sign in&lt;/code&gt; screen appears in the editor view. If you don't have an account, select &lt;code&gt;Sign up&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--O82uoGnz--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2Faeaabae02e8adff238ae08b8.png%253Fsha%253D01a0bc2f15db3778f85af1a7a0e091a1bca1c1c4" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--O82uoGnz--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2Faeaabae02e8adff238ae08b8.png%253Fsha%253D01a0bc2f15db3778f85af1a7a0e091a1bca1c1c4" alt="signin" width="858" height="874"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Upon successful sign-in, you'll see a screen like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--Cc-z29QV--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2Fa02ef4d31f03de7b2740581b.png%253Fsha%253D8c9e9461b293743f0a7282f62365afe01630f734" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--Cc-z29QV--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2Fa02ef4d31f03de7b2740581b.png%253Fsha%253D8c9e9461b293743f0a7282f62365afe01630f734" alt="signin-success" width="866" height="1002"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating UI with Natural Language
&lt;/h3&gt;

&lt;p&gt;First, I tried instructing UI creation using natural language. I entered the following prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;I want to create a Pokédex. Make it possible to view all 151 Pokémon from the first generation.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--6rhuhb20--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2F31700337a35815c5ac34344b.png%253Fsha%253D431cc9d9ab8eba3f2bae040a3dfcffc48887039b" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--6rhuhb20--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2F31700337a35815c5ac34344b.png%253Fsha%253D431cc9d9ab8eba3f2bae040a3dfcffc48887039b" alt="demo1-0" width="1100" height="878"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you run the chat, it lists what technology stack to use for designing the frontend.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--aDgIB2wF--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2F02e4382776d15d9a39472b9c.png%253Fsha%253D06d86726929c5471bffd828cc464e5c05a1b4117" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--aDgIB2wF--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2F02e4382776d15d9a39472b9c.png%253Fsha%253D06d86726929c5471bffd828cc464e5c05a1b4117" alt="demo1-1" width="1094" height="928"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Framework: React 19 TypeScript&lt;/li&gt;
&lt;li&gt;API Framework: RTK, RTK Query&lt;/li&gt;
&lt;li&gt;Router: React Router v7 (declarative mode)&lt;/li&gt;
&lt;li&gt;Component Library: MUI v7&lt;/li&gt;
&lt;li&gt;Styling: Emotion&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The technology stack choices provided seem a bit different from what's typically preferred in Japan. You can change the technology stack used from &lt;code&gt;Configure stack&lt;/code&gt; if needed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs---S4wCJHK--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2Fbf1815f7b5b0d10d6a220c85.png%253Fsha%253De386bab2b613f91c0c473a56ef5992d58fb74e4f" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs---S4wCJHK--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2Fbf1815f7b5b0d10d6a220c85.png%253Fsha%253De386bab2b613f91c0c473a56ef5992d58fb74e4f" alt="demo1-2" width="1200" height="1381"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Available categories include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Framework&lt;/li&gt;
&lt;li&gt;API &amp;amp; State Management&lt;/li&gt;
&lt;li&gt;Router&lt;/li&gt;
&lt;li&gt;Components&lt;/li&gt;
&lt;li&gt;Styling&lt;/li&gt;
&lt;li&gt;Icons&lt;/li&gt;
&lt;li&gt;Global Instructions&lt;/li&gt;
&lt;li&gt;Advanced Configurations&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After deciding on the technology stack, it moves to the Planning Phase. The Planning Phase lists what views and components to create. You can edit or provide input if there are issues.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--uumry_3N--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2F6d0a48cb9aed564a2ee0c13a.png%253Fsha%253D9bac71218e589d5c849def8f001f9ba2f537adb8" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--uumry_3N--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2F6d0a48cb9aed564a2ee0c13a.png%253Fsha%253D9bac71218e589d5c849def8f001f9ba2f537adb8" alt="demo1-5" width="1200" height="1233"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If there are no issues with the Planning Phase content, you execute it. After execution, a &lt;code&gt;Run in Sandbox&lt;/code&gt; button appears as shown in the image below.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--klkBFl4D--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2Fcaae43034c0ca06dd11f1af1.png%253Fsha%253Db5165f43d601f7d6dc843ef231ea1897dee96fc2" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--klkBFl4D--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2Fcaae43034c0ca06dd11f1af1.png%253Fsha%253Db5165f43d601f7d6dc843ef231ea1897dee96fc2" alt="demo1-6" width="1200" height="629"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you run &lt;code&gt;Run in Sandbox&lt;/code&gt;, you can view and interact with the actual frontend created on localhost. &lt;strong&gt;The ability to preview AI-generated frontend in a sandbox is one of Kombai's key strengths&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--2lprTVzB--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2F402b94ce41d11c2f2fc738cd.png%253Fsha%253Da6c168a71e8d23a570511077f18999624d45a91b" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--2lprTVzB--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2F402b94ce41d11c2f2fc738cd.png%253Fsha%253Da6c168a71e8d23a570511077f18999624d45a91b" alt="demo1-7" width="564" height="184"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The Pokédex created this time looks like this. It has a MUI-style UI.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--aOqo5MI3--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2Fc45ab3453b37a582c88be8bd.png%253Fsha%253D5779f2a1728979e9014045e7c8b67b3050f411b0" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--aOqo5MI3--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2Fc45ab3453b37a582c88be8bd.png%253Fsha%253D5779f2a1728979e9014045e7c8b67b3050f411b0" alt="demo1-8" width="1200" height="687"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It prepared 5 mock data entries for me.&lt;/p&gt;

&lt;p&gt;I tried adding the following additional prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Make it 151 types of Pokémon. Also, make all UI language Japanese.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The Pokédex generated by the additional instruction is shown in the image below. It properly supported Japanese and prepared 151 types of mock data.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--aN2O5D3Z--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2Fa6c885bac3ecb995d61be9a0.png%253Fsha%253Dd6f611889184c9ff0773b245848014931d46c5fa" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--aN2O5D3Z--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2Fa6c885bac3ecb995d61be9a0.png%253Fsha%253Dd6f611889184c9ff0773b245848014931d46c5fa" alt="demo1-9" width="1200" height="684"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;UI interactions were also possible in the sandbox. For example, when selecting a Pokémon, I could check individual Pokémon details.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--MvADxybV--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2F30e2586d25273e76a1bb483e.png%253Fsha%253D53343fc7a59246eaaba545eff17b7a19498286dd" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--MvADxybV--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2F30e2586d25273e76a1bb483e.png%253Fsha%253D53343fc7a59246eaaba545eff17b7a19498286dd" alt="demo1-10" width="1200" height="1415"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Beyond this, &lt;strong&gt;I was able to confirm that search and filter functions worked correctly within the sandbox&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;If there are no issues with changes in the sandbox, you can save the changes. Conversely, unless you adopt the changes, Kombai won't reflect changes to your local work environment. Items developed in the sandbox can also be restored to checkpoints in the chat.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--5Nc50s5k--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2F111eca5bce3c06b72b46f016.png%253Fsha%253D43f70d31dfd58f979b3eecdf7b4a2df73d9d0fd4" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--5Nc50s5k--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2F111eca5bce3c06b72b46f016.png%253Fsha%253D43f70d31dfd58f979b3eecdf7b4a2df73d9d0fd4" alt="restore" width="874" height="452"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The frontend output for this Pokédex is as follows:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--V116dczp--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2Fee7c5d0121038572c295b086.png%253Fsha%253De6071cc7890020c58a5610686b1b36198a674100" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--V116dczp--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2Fee7c5d0121038572c295b086.png%253Fsha%253De6071cc7890020c58a5610686b1b36198a674100" alt="demo1-11" width="1200" height="1370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kombai not only created components but also organized the frontend folder structure.&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating UI from Figma
&lt;/h3&gt;

&lt;p&gt;Kombai also provides "Figma to UI" functionality that imports Figma designs and converts them to UI. You can add it from &lt;code&gt;Add Figma link&lt;/code&gt; in the bottom right of the chat.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--SSzglHIB--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2F94ae156619d192712ffe8fa2.png%253Fsha%253Da720a22f5567dd762ee9eff990aa6b0972717ec8" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--SSzglHIB--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2F94ae156619d192712ffe8fa2.png%253Fsha%253Da720a22f5567dd762ee9eff990aa6b0972717ec8" alt="figma-link" width="444" height="260"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;A dialog for entering the Figma URL appears. The dialog also explains how to get the Figma URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Right-click frame &amp;gt; "Copy/Paste as" &amp;gt; "Copy link to selection"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first time requires authentication to connect Figma and Kombai.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--d46GXDGe--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2F4d6fff5d5ac736ffc9618dcc.png%253Fsha%253D6e1b2366af7a103fbf7d6115db024f0debdeb0bb" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--d46GXDGe--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2F4d6fff5d5ac736ffc9618dcc.png%253Fsha%253D6e1b2366af7a103fbf7d6115db024f0debdeb0bb" alt="figma-url" width="1080" height="584"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When the Figma URL is correctly loaded, the Figma design appears in the prompt as shown in the image below. This design is treated as a &lt;code&gt;@&lt;/code&gt; resource, so it was possible to load multiple Figma designs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--561NWvuJ--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2F35673346e27d1d384d99b343.png%253Fsha%253Df8c89b9e348878fe9a4c550adb51044e40109e68" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--561NWvuJ--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2F35673346e27d1d384d99b343.png%253Fsha%253Df8c89b9e348878fe9a4c550adb51044e40109e68" alt="figma-view" width="1086" height="1222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'll introduce some examples of UI created from actual Figma designs. For reference, all were one-shot prompts.&lt;/p&gt;

&lt;p&gt;I'll show three examples, so &lt;strong&gt;please compare the Figma designs with Kombai's output&lt;/strong&gt;. Each consumed about 20-40 credits.&lt;/p&gt;

&lt;h4&gt;
  
  
  Example 1
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Figma Design&lt;/strong&gt; (&lt;a href="https://www.figma.com/community/file/1252561852327562039" rel="noopener noreferrer"&gt;link&lt;/a&gt;):&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--k7w8ha84--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2Fc1a0459c1723ae996cde2e37.png%253Fsha%253D339c5ccd86aef5e7c9512c574b8fe8bcb9ba2d68" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--k7w8ha84--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2Fc1a0459c1723ae996cde2e37.png%253Fsha%253D339c5ccd86aef5e7c9512c574b8fe8bcb9ba2d68" alt="figma-1" width="1200" height="1135"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kombai's Output&lt;/strong&gt;:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--Y6e_n-cb--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2Fd7a1b99cd29c10c48bce4ff0.png%253Fsha%253D48c8a227c063fee60b693c9cb43c4b33f910ce4c" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--Y6e_n-cb--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2Fd7a1b99cd29c10c48bce4ff0.png%253Fsha%253D48c8a227c063fee60b693c9cb43c4b33f910ce4c" alt="example-1" width="1200" height="688"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Example 2
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Figma Design&lt;/strong&gt; (&lt;a href="https://www.figma.com/design/eaY2PdzUqfFrSlkHBd3j0e/Stock-Portfolio-Dashboard--Community-?node-id=0-1&amp;amp;p=f&amp;amp;t=QYKekSD0zUGvLPZK-0" rel="noopener noreferrer"&gt;link&lt;/a&gt;):&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--T0RmN1OZ--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2F8a1e5578cb2de64db41df647.png%253Fsha%253D31f48c88b1d786faa54a2c3c43b32f0e2e0890dc" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--T0RmN1OZ--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2F8a1e5578cb2de64db41df647.png%253Fsha%253D31f48c88b1d786faa54a2c3c43b32f0e2e0890dc" alt="figma-2" width="1200" height="818"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kombai's Output&lt;/strong&gt;:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--lZ6F_Z_8--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2Fbd837a0869c13d74df1d1c65.png%253Fsha%253D0595f442bbe8e8727e0bb8b0610173296d50fb38" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--lZ6F_Z_8--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2Fbd837a0869c13d74df1d1c65.png%253Fsha%253D0595f442bbe8e8727e0bb8b0610173296d50fb38" alt="example-2" width="1200" height="690"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h4&gt;
  
  
  Example 3
&lt;/h4&gt;

&lt;p&gt;&lt;strong&gt;Figma Design&lt;/strong&gt; (&lt;a href="https://www.figma.com/design/79YtCDYtmvzSclE1f286cA/Stock-UI--Community-?node-id=0-1&amp;amp;p=f&amp;amp;t=aFWcXT6qVHkw349q-0" rel="noopener noreferrer"&gt;link&lt;/a&gt;):&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--yLcK_WxT--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2Fd781143f798eba26b85257b9.png%253Fsha%253D793033d29cea9f2c65199c10dd1867f6880d6d42" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--yLcK_WxT--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2Fd781143f798eba26b85257b9.png%253Fsha%253D793033d29cea9f2c65199c10dd1867f6880d6d42" alt="figma-3" width="1200" height="675"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Kombai's Output&lt;/strong&gt;:&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--HtVuICdL--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2F700b962b6239db88072c056a.png%253Fsha%253D310f3fe94fabdcc8ce849301f42555071eb12651" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fres.cloudinary.com%2Fzenn%2Fimage%2Ffetch%2Fs--HtVuICdL--%2Fc_limit%252Cf_auto%252Cfl_progressive%252Cq_auto%252Cw_1200%2Fhttps%3A%2F%2Fstorage.googleapis.com%2Fzenn-user-upload%2Fdeployed-images%2F700b962b6239db88072c056a.png%253Fsha%253D310f3fe94fabdcc8ce849301f42555071eb12651" alt="example-3" width="1200" height="688"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My impressions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Not pixel-perfect reproduction&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sufficient as an initial mock&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Seems to struggle a bit with transparency effects&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Can be improved with few-shot prompting&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Kombai's official site also provides design reference examples, which should be helpful for understanding what kinds of UI can be generated.&lt;/p&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;This time I introduced "Kombai," an AI tool for Figma to Code conversion.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Easy to use as VSCode or Cursor plugin&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Excellent sandbox UI preview functionality&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;High UI compilation success rate&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Not pixel-perfect for Figma to Code, but excellent as a starting point&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While this was a frontend-focused AI tool, I think we'll see more domain-specific coding tools in the future.&lt;/p&gt;

&lt;p&gt;I hope this helps anyone who's interested.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kombai.com/" rel="noopener noreferrer"&gt;Kombai - Official Website&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.producthunt.com/products/kombai" rel="noopener noreferrer"&gt;Kombai - Product Hunt&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.kombai.com/core-features/configure-tech-stack" rel="noopener noreferrer"&gt;Kombai Documentation - Tech Stack Configuration&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kombai.com/examples" rel="noopener noreferrer"&gt;Kombai Examples&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.figma.com/community/file/1252561852327562039" rel="noopener noreferrer"&gt;Figma Community File - Example 1&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.figma.com/design/eaY2PdzUqfFrSlkHBd3j0e/Stock-Portfolio-Dashboard--Community-?node-id=0-1&amp;amp;p=f&amp;amp;t=QYKekSD0zUGvLPZK-0" rel="noopener noreferrer"&gt;Figma Design - Stock Portfolio Dashboard&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.figma.com/design/79YtCDYtmvzSclE1f286cA/Stock-UI--Community-?node-id=0-1&amp;amp;p=f&amp;amp;t=aFWcXT6qVHkw349q-0" rel="noopener noreferrer"&gt;Figma Design - Stock UI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;Follow me on &lt;a href="https://x.com/gaishi_narou" rel="noopener noreferrer"&gt;X/Twitter&lt;/a&gt; for more tech content!&lt;/em&gt;&lt;/p&gt;

</description>
      <category>kombai</category>
      <category>frontend</category>
      <category>ai</category>
      <category>webdev</category>
    </item>
    <item>
      <title>Enhancing Claude Code with MCP Servers and Subagents</title>
      <dc:creator>Oikon</dc:creator>
      <pubDate>Sat, 14 Jun 2025 17:01:04 +0000</pubDate>
      <link>https://dev.to/oikon/enhancing-claude-code-with-mcp-servers-and-subagents-29dd</link>
      <guid>https://dev.to/oikon/enhancing-claude-code-with-mcp-servers-and-subagents-29dd</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;I've been using Claude Code daily for personal development projects. However, I've encountered several cases where Claude struggled to solve complex problems dependent on specific library versions during web app development.&lt;/p&gt;

&lt;p&gt;After extensive experimentation, I discovered that &lt;strong&gt;enabling Model Context Protocol (MCP) servers for Claude Code significantly improves its problem-solving capabilities&lt;/strong&gt;. This article shares my findings and practical implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Background and Motivation
&lt;/h2&gt;

&lt;p&gt;While Claude Code is powerful, it sometimes lacks current information about rapidly evolving libraries and frameworks. This limitation becomes particularly evident when dealing with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Version-specific compatibility issues&lt;/li&gt;
&lt;li&gt;Recent library updates and breaking changes&lt;/li&gt;
&lt;li&gt;Latest best practices and solutions&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  MCP Servers Used
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Context7&lt;/strong&gt;: Version-specific API documentation retrieval&lt;br&gt;
&lt;strong&gt;Brave-Search&lt;/strong&gt;: Web search functionality&lt;/p&gt;

&lt;p&gt;Both are well-established MCP servers. Additionally, I experimented with &lt;strong&gt;custom slash commands that leverage subagents with MCP servers&lt;/strong&gt; for more streamlined workflows.&lt;/p&gt;
&lt;h2&gt;
  
  
  Understanding Model Context Protocol (MCP)
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuodotldbmq2ldcwp5713.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuodotldbmq2ldcwp5713.png" alt=" " width="800" height="546"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;MCP is a protocol proposed by Anthropic that connects AI systems with external tools. Simply put, &lt;strong&gt;it's a standard that enables AI agents to use external tools&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;In our setup:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Host with MCP client = &lt;strong&gt;Claude Code&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;MCP server A/C = &lt;strong&gt;Context7 MCP server&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;MCP server C = &lt;strong&gt;Brave-Search MCP server&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Context7 MCP Server
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/upstash/context7" rel="noopener noreferrer"&gt;https://github.com/upstash/context7&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Context7, developed by Upstash, is &lt;strong&gt;an MCP server that retrieves versioned API documentation&lt;/strong&gt;. It addresses the common issue where AI models have outdated information about rapidly evolving OSS libraries.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxet6xi90r6nrbdnpgiid.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxet6xi90r6nrbdnpgiid.png" alt=" " width="800" height="674"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Supported libraries are available at &lt;a href="https://context7.com/" rel="noopener noreferrer"&gt;context7.com&lt;/a&gt;. The coverage includes most common web development libraries.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setup for Claude Code:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Remote MCP Server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add &lt;span class="nt"&gt;--transport&lt;/span&gt; sse context7 https://mcp.context7.com/sse
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Local MCP Server:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add context7 &lt;span class="nt"&gt;--&lt;/span&gt; npx &lt;span class="nt"&gt;-y&lt;/span&gt; @upstash/context7-mcp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Brave-Search MCP Server
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://github.com/modelcontextprotocol/servers-archived/tree/main/src/brave-search" rel="noopener noreferrer"&gt;https://github.com/modelcontextprotocol/servers-archived/tree/main/src/brave-search&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Brave-Search provides &lt;strong&gt;web search functionality as an MCP server&lt;/strong&gt;. While Claude Code has built-in web search, I found the dedicated MCP server more effective, especially when working with subagents.&lt;/p&gt;

&lt;p&gt;The free plan allows up to 2,000 queries per month. Get your API key from the &lt;a href="https://brave.com/search/api/" rel="noopener noreferrer"&gt;official site&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setup:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;claude mcp add brave-search &lt;span class="nt"&gt;-s&lt;/span&gt; user &lt;span class="nt"&gt;--&lt;/span&gt; &lt;span class="nb"&gt;env &lt;/span&gt;&lt;span class="nv"&gt;BRAVE_API_KEY&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;YOUR_API_KEY_HERE&lt;span class="sb"&gt;`&lt;/span&gt; npx &lt;span class="nt"&gt;-y&lt;/span&gt; @modelcontextprotocol/server-brave-search
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Security Note&lt;/strong&gt;: While these servers aren't in Anthropic's official repository (Brave-Search is archived), they're widely trusted. Always exercise caution with MCP servers due to potential security risks like tool poisoning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Claude Code Subagents
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Subagents are a default feature in Claude Code&lt;/strong&gt; that many users overlook. Tasks shown under &lt;code&gt;Task&lt;/code&gt; are executed by subagents, particularly for web fetching and file reading operations.&lt;/p&gt;

&lt;p&gt;According to &lt;a href="https://www.anthropic.com/engineering/claude-code-best-practices" rel="noopener noreferrer"&gt;Anthropic's official documentation&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;This is the part of the workflow where you should consider strong use of &lt;strong&gt;subagents&lt;/strong&gt;, especially for complex problems. Telling Claude to use &lt;strong&gt;subagents&lt;/strong&gt; to verify details or investigate particular questions it might have, especially early on in a conversation or task, tends to preserve context availability without much downside in terms of lost efficiency.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Subagent Characteristics
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Lightweight execution&lt;/li&gt;
&lt;li&gt;Parallel operation capability&lt;/li&gt;
&lt;li&gt;Access to parent agent's available tools&lt;/li&gt;
&lt;li&gt;Independent context windows&lt;/li&gt;
&lt;li&gt;Task-specific lifecycle (created and destroyed per task)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This architecture enables &lt;strong&gt;parent agents to delegate tasks to subagents for execution&lt;/strong&gt;, with parallel processing capabilities for improved efficiency.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flau9lkgnm8y9gozv69x0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flau9lkgnm8y9gozv69x0.png" alt=" " width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Practical Implementation: Using MCP Servers with Subagents
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Without Subagents
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frx3lzw06e7qc4mmgermg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frx3lzw06e7qc4mmgermg.png" alt=" " width="800" height="867"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When not explicitly specifying subagent usage, Claude Code directly calls Context7 and Brave-Search MCP servers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;CLAUDE.md configuration:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="p"&gt;-&lt;/span&gt; You can use web search including &lt;span class="sb"&gt;`use brave-search`&lt;/span&gt; MCP to search the latest solution.
&lt;span class="p"&gt;-&lt;/span&gt; You should check the latest Next.js, Node.js, and other libraries with &lt;span class="sb"&gt;`use context7`&lt;/span&gt; MCP.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complete context inheritance from Claude Code&lt;/li&gt;
&lt;li&gt;Seamless problem-solving with current context&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Drawbacks:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Higher context window consumption&lt;/li&gt;
&lt;li&gt;Faster rate limit approach&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  With Subagents
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqqckbbrs1qx8f31h76m6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqqckbbrs1qx8f31h76m6.png" alt=" " width="800" height="338"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Include "&lt;strong&gt;use subagent&lt;/strong&gt;" or "&lt;strong&gt;multiple subagents&lt;/strong&gt;" in your prompts to delegate tasks to subagents.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Parallel information processing&lt;/li&gt;
&lt;li&gt;Clear separation of concerns&lt;/li&gt;
&lt;li&gt;Reduced parent context window pressure&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Drawbacks:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Minimal context sharing with subagents&lt;/li&gt;
&lt;li&gt;Potentially less targeted search results&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Pros and Cons Summary
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple implementation&lt;/li&gt;
&lt;li&gt;No RAG system required&lt;/li&gt;
&lt;li&gt;Access to latest information&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Context window consumption&lt;/li&gt;
&lt;li&gt;Increased token usage&lt;/li&gt;
&lt;li&gt;Claude Code's limited MCP server proficiency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The approach serves as &lt;strong&gt;improving the probability of successful code generation&lt;/strong&gt; rather than a guaranteed solution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Advanced Usage: Custom Slash Commands
&lt;/h2&gt;

&lt;p&gt;Instead of repeatedly typing &lt;code&gt;use subagent&lt;/code&gt; and &lt;code&gt;use Context7&lt;/code&gt;, I recommend creating custom slash commands for streamlined bug resolution.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Setup:&lt;/strong&gt; Place Markdown files in the commands directory:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Global: &lt;code&gt;~/.claude/commands/&lt;/code&gt; (prefix: &lt;code&gt;/user:&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Project-specific: &lt;code&gt;&amp;lt;project root&amp;gt;/.claude/commands/&lt;/code&gt; (prefix: &lt;code&gt;/project:&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Example - &lt;code&gt;~/.claude/commands/bugfix.md&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;Fix bug from user provided bug description: $ARGUMENTS
&lt;span class="p"&gt;
1.&lt;/span&gt; Understand the bug description and think the root cause. Try to recreate the issue.
&lt;span class="p"&gt;2.&lt;/span&gt; Fix the issue. Use &lt;span class="sb"&gt;`context7`&lt;/span&gt; and &lt;span class="sb"&gt;`brave-search`&lt;/span&gt; MCP tools to understand the error. 
These MCP tool searching should be done by multiple subagents. Also use native Web search subagent for issue investigation.
&lt;span class="p"&gt;3.&lt;/span&gt; If there is another error, always repeat this debugging process from 1 to 2.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fat822lcvzljvtb9cyeq2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fat822lcvzljvtb9cyeq2.png" alt=" " width="800" height="153"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;/user:bugfix Next.js Hydration error needs fixing.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Claude Code understands the predefined execution steps and prepares appropriate tasks automatically.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdsg2cy7r1fcr3f9mleud.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdsg2cy7r1fcr3f9mleud.png" alt=" " width="800" height="113"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Case Study: Solving Next.js 15 Hydration Errors
&lt;/h2&gt;

&lt;p&gt;In my testing, Claude Code successfully resolved Next.js 15 hydration errors that it previously couldn't handle alone. The combination of:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Context7 for latest Next.js documentation&lt;/li&gt;
&lt;li&gt;Brave-Search for recent solution discussions
&lt;/li&gt;
&lt;li&gt;Subagents for parallel information gathering&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This resulted in accurate identification and resolution of Next.js 15 and Material-UI compatibility issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;This article explored using MCP servers with subagents to address Claude Code's limitation with current library information. While the implementation focused on search-related MCP servers, &lt;strong&gt;filesystem and popular Obsidian MCP servers could be equally effective&lt;/strong&gt; for accessing local documentation.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Key takeaways:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MCP servers enhance Claude Code's problem-solving capabilities&lt;/li&gt;
&lt;li&gt;Subagents provide parallel processing and context management benefits&lt;/li&gt;
&lt;li&gt;Custom slash commands streamline complex workflows&lt;/li&gt;
&lt;li&gt;The approach improves success probability rather than guaranteeing solutions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Future outlook:&lt;/strong&gt; Subagent parallelization is an active research area. While we implemented basic multiple-subagent search within Claude Code, official improvements to this functionality are likely forthcoming.&lt;/p&gt;

&lt;p&gt;The combination of MCP servers and subagents represents a significant step toward more capable AI-assisted development workflows.&lt;/p&gt;

&lt;h2&gt;
  
  
  Note
&lt;/h2&gt;

&lt;p&gt;This original document is written in Japanese.&lt;/p&gt;

&lt;p&gt;You can find original document &lt;a href="https://zenn.dev/oikon/articles/82c9a52dc45810" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.anthropic.com/engineering/claude-code-best-practices" rel="noopener noreferrer"&gt;Anthropic - Claude Code Best Practices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.anthropic.com/engineering/built-multi-agent-research-system" rel="noopener noreferrer"&gt;Anthropic - How we built our multi-agent research system&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://modelcontextprotocol.io/introduction" rel="noopener noreferrer"&gt;Model Context Protocol Introduction&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://context7.com/" rel="noopener noreferrer"&gt;Context7 Official Site&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/upstash/context7" rel="noopener noreferrer"&gt;Context7 GitHub Repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/modelcontextprotocol/servers-archived/tree/main/src/brave-search" rel="noopener noreferrer"&gt;Brave-Search MCP Server&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>claude</category>
      <category>anthropic</category>
    </item>
    <item>
      <title>Improving Japanese Input UX in Multilingual Applications: Properly Handling IME Conversion</title>
      <dc:creator>Oikon</dc:creator>
      <pubDate>Sun, 09 Mar 2025 10:00:00 +0000</pubDate>
      <link>https://dev.to/oikon/improving-japanese-input-ux-in-multilingual-applications-properly-handling-ime-conversion-2ild</link>
      <guid>https://dev.to/oikon/improving-japanese-input-ux-in-multilingual-applications-properly-handling-ime-conversion-2ild</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;In global web application development, multilingual support is an essential requirement. However, languages that use IME (Input Method Editor) such as Japanese, Chinese, and Korean have unique input and conversion processes that require special consideration. This article explains issues with form operations in Japanese input and their solutions.&lt;/p&gt;

&lt;h2&gt;
  
  
  Target Audience
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Web application developers&lt;/li&gt;
&lt;li&gt;Frontend developers&lt;/li&gt;
&lt;li&gt;Those involved in developing globally accessible applications&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Problem: Event Handling During IME Conversion
&lt;/h2&gt;

&lt;p&gt;Japanese input involves a conversion process from "hiragana" to "katakana/kanji". During this process, the following issue often occurs:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fujzkm85hgc3wgbnvlgs7.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fujzkm85hgc3wgbnvlgs7.gif" alt=" " width="534" height="436"&gt;&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Example: When trying to search for "Tokyo Tower"
1. Type "とうきょうたわー" (hiragana)
2. Press spacebar to display conversion candidates
3. Press Enter to confirm "東京タワー" (kanji/katakana)
4. This Enter key mistakenly triggers the search execution
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This results in an unintended search for "Tokyo Tower" and degrades the user experience. This problem is particularly noticeable in UIs where the Enter key executes actions, such as search forms and chat interfaces.&lt;/p&gt;

&lt;h2&gt;
  
  
  Technical Background: Composition Events
&lt;/h2&gt;

&lt;p&gt;When inputting with IME, "Composition" events occur in addition to standard keyboard events:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;compositionstart&lt;/code&gt;: Start of conversion process&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;compositionupdate&lt;/code&gt;: Update of text during conversion&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;compositionend&lt;/code&gt;: End of conversion process&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Additionally, the &lt;code&gt;KeyboardEvent&lt;/code&gt; object includes an &lt;code&gt;isComposing&lt;/code&gt; property that indicates whether IME conversion is in progress. Understanding this characteristic is the first step toward improving UX.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution: Using the isComposing Property
&lt;/h2&gt;

&lt;p&gt;IME support can be implemented in frontend frameworks like React, Vue, and Angular as follows:&lt;/p&gt;

&lt;h3&gt;
  
  
  React Implementation Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;SearchField&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;onSearch&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleKeyDown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Ignore Enter during IME conversion confirmation&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Enter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nativeEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isComposing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;searchTerm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;onSearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;input&lt;/span&gt; 
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; 
      &lt;span class="na"&gt;onKeyDown&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleKeyDown&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt; 
      &lt;span class="na"&gt;placeholder&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Search..."&lt;/span&gt; 
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Vue Implementation Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight vue"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;input&lt;/span&gt; 
    &lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"text"&lt;/span&gt; 
    &lt;span class="err"&gt;@&lt;/span&gt;&lt;span class="na"&gt;keydown=&lt;/span&gt;&lt;span class="s"&gt;"handleKeyDown"&lt;/span&gt; 
    &lt;span class="na"&gt;placeholder=&lt;/span&gt;&lt;span class="s"&gt;"Search..."&lt;/span&gt; 
  &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;template&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;

&lt;span class="nt"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;methods&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;handleKeyDown&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Enter&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isComposing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;searchTerm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;target&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;$emit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;search&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/&lt;/span&gt;&lt;span class="k"&gt;script&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  HTML/JavaScript Implementation Example
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;querySelector&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;input&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;keydown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Enter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isComposing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;searchTerm&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;performSearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;searchTerm&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Handling More Complex UI Components
&lt;/h2&gt;

&lt;p&gt;The same approach can be applied when using UI libraries like Material-UI, Ant Design, and Chakra UI. Here's an implementation example with Material-UI's Autocomplete component:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Autocomplete&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;TextField&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;@mui/material&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;SearchComponent&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;onSearch&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;options&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;inputValue&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;setInputValue&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useState&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;handleKeyDown&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Enter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;nativeEvent&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;isComposing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;preventDefault&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
      &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;onSearch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;inputValue&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;

  &lt;span class="k"&gt;return &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Autocomplete&lt;/span&gt;
      &lt;span class="na"&gt;freeSolo&lt;/span&gt;
      &lt;span class="na"&gt;options&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;options&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;inputValue&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;inputValue&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;onInputChange&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;setInputValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;newValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
      &lt;span class="na"&gt;renderInput&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;TextField&lt;/span&gt;
          &lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
          &lt;span class="na"&gt;label&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"Search"&lt;/span&gt;
          &lt;span class="na"&gt;variant&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="s"&gt;"outlined"&lt;/span&gt;
          &lt;span class="na"&gt;onKeyDown&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;handleKeyDown&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Testing Methods
&lt;/h2&gt;

&lt;p&gt;To test IME-related implementations:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Operate the application in Japanese input mode&lt;/li&gt;
&lt;li&gt;Enter "hiragana" and display conversion candidates&lt;/li&gt;
&lt;li&gt;Press Enter to confirm the conversion&lt;/li&gt;
&lt;li&gt;Verify that pressing Enter again executes the search&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;It's ideal to test in a Japanese environment, but if Japanese IME is not available in your development environment, the following tools can be helpful:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Windows: Microsoft IME&lt;/li&gt;
&lt;li&gt;macOS: Japanese Input System&lt;/li&gt;
&lt;li&gt;Online emulators: Some browser extensions can simulate IME input&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Browser Compatibility Notes
&lt;/h2&gt;

&lt;p&gt;While the &lt;code&gt;isComposing&lt;/code&gt; property is widely supported in modern browsers, it may behave differently in older browsers. As an alternative approach to ensure compatibility, consider implementing using &lt;code&gt;compositionstart&lt;/code&gt; and &lt;code&gt;compositionend&lt;/code&gt; events:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;isComposing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;compositionstart&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;isComposing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;compositionend&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;isComposing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="nx"&gt;input&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;addEventListener&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;keydown&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;event&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;Enter&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;isComposing&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Execute search process&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;In multilingual applications, input processing that considers IME is essential. Especially in cases where the Enter key executes actions such as in search forms and chat interfaces, it's important to use the &lt;code&gt;isComposing&lt;/code&gt; property to distinguish between IME conversion processes and normal input.&lt;/p&gt;

&lt;p&gt;This small consideration greatly improves the experience for users of languages such as Japanese, Chinese, and Korean. In global application development, attention to such details leads to true multilingual support.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/API/CompositionEvent" rel="noopener noreferrer"&gt;MDN Web Docs: Composition Events&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://stackoverflow.com/questions/27759380/how-to-detect-ime-conversion-status-without-focus-events" rel="noopener noreferrer"&gt;Stack Overflow: Handling IME in JavaScript&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>ime</category>
      <category>javascript</category>
    </item>
    <item>
      <title>How to Implement Dynamic Multilingual Sitemap with 40,000 URLs in Next.js App Router</title>
      <dc:creator>Oikon</dc:creator>
      <pubDate>Sun, 09 Feb 2025 13:36:33 +0000</pubDate>
      <link>https://dev.to/oikon/how-to-implement-dynamic-multilingual-sitemap-with-40000-urls-in-nextjs-app-router-41ko</link>
      <guid>https://dev.to/oikon/how-to-implement-dynamic-multilingual-sitemap-with-40000-urls-in-nextjs-app-router-41ko</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This article explains implementing a dynamic sitemap for a large-scale website using Next.js App Router. I'll share the implementation method for a multilingual site containing over 40,000 content items.&lt;/p&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;By combining Next.js sitemap API with 24-hour caching, we implemented a practical dynamic sitemap solution for large-scale sites. This approach minimizes the impact on frontend build time while enabling daily data updates.&lt;/p&gt;

&lt;h2&gt;
  
  
  Development Environment
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Frontend: Next.js (App Router)&lt;/li&gt;
&lt;li&gt;Backend: Express + MongoDB&lt;/li&gt;
&lt;li&gt;Infrastructure: Vercel (Frontend), Heroku (Backend)&lt;/li&gt;
&lt;li&gt;Languages: 2 (bilingual)&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Context
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Over 20,000 unique pages&lt;/li&gt;
&lt;li&gt;Each page has 2 language variations (total: 40,000+ URLs)&lt;/li&gt;
&lt;li&gt;Daily data updates&lt;/li&gt;
&lt;li&gt;Sitemap required for SEO requirements&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Understanding Sitemap Generation
&lt;/h2&gt;

&lt;p&gt;There are three main approaches to sitemap generation:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Static Generation&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Fast response time&lt;/li&gt;
&lt;li&gt;Low server load&lt;/li&gt;
&lt;li&gt;Longer build times&lt;/li&gt;
&lt;li&gt;Difficult to handle immediate data updates&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Dynamic Generation&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easy reflection of latest data&lt;/li&gt;
&lt;li&gt;No impact on build time&lt;/li&gt;
&lt;li&gt;Higher server load&lt;/li&gt;
&lt;li&gt;Potential slower response times&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ISR (Incremental Static Regeneration)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Balanced approach between static and dynamic&lt;/li&gt;
&lt;li&gt;Easy cache control&lt;/li&gt;
&lt;li&gt;Slightly more complex implementation&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I had written about basic sitemap generation in the following document:&lt;br&gt;
&lt;a href="https://dev.to/s4yuba/implementing-multilingual-sitemap-with-next-intl-in-nextjs-app-router-1354"&gt;Implementing Multilingual Sitemap with next-intl in Next.js App Router&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Implementation
&lt;/h2&gt;

&lt;p&gt;We adopted an implementation combining Next.js sitemap API with 24-hour caching:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/sitemap.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MetadataRoute&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;BASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;production&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; 
  &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;localhost:3000&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;API_BASE_URL&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NODE_ENV&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;production&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
  &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NEXT_PUBLIC_API_BASE_URL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/api/util`&lt;/span&gt;
  &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:3500/api/util&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sitemap&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;MetadataRoute&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Sitemap&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;locales&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ja&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/about&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/products&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/contact&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

  &lt;span class="c1"&gt;// Generate static routes&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;staticRoutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flatMap&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
    &lt;span class="nx"&gt;locales&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;BASE_URL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;route&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;lastModified&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
      &lt;span class="na"&gt;changeFrequency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;monthly&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;}))&lt;/span&gt;
  &lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Fetch product data with caching&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;API_BASE_URL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/products`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;revalidate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;86400&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="c1"&gt;// Cache for 24 hours&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Cache-Control&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;public, max-age=86400&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Failed to fetch products: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;statusText&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Generate product URLs&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;productRoutes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flatMap&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="na"&gt;product&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
      &lt;span class="nx"&gt;locales&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
        &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;BASE_URL&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/product/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;lastModified&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;updatedAt&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="na"&gt;changeFrequency&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;daily&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}))&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;staticRoutes&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;productRoutes&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error generating sitemap:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;staticRoutes&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Fallback to static routes on error&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Backend API implementation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Express route handler&lt;/span&gt;
&lt;span class="nx"&gt;router&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/products&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;req&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Fetch minimal required data from MongoDB&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;products&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="p"&gt;{},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;lastUpdateDate&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;lean&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;products&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Failed to fetch products:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="nx"&gt;res&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;status&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;500&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
      &lt;span class="na"&gt;message&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Error fetching products&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;error&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nb"&gt;Error&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;message&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Implementation Results
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Total URLs: 42,000 (21,000 for en, ja)&lt;/li&gt;
&lt;li&gt;File size: 4.6MB&lt;/li&gt;
&lt;li&gt;Generation time: Under 5 seconds&lt;/li&gt;
&lt;li&gt;Impact on build time: Minimal&lt;/li&gt;
&lt;li&gt;Cache duration: 24 hours&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Checking results
&lt;/h3&gt;

&lt;p&gt;You can check the generated sitemap in dev environment, &lt;code&gt;localhost:3000/sitemap.xml&lt;/code&gt;. &lt;/p&gt;

&lt;h2&gt;
  
  
  Key Implementation Considerations
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Caching Strategy&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use both Next.js revalidation and HTTP caching&lt;/li&gt;
&lt;li&gt;24-hour cache balances freshness and performance&lt;/li&gt;
&lt;li&gt;Implement fallback to static routes on errors&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Error Handling&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Graceful degradation to static routes&lt;/li&gt;
&lt;li&gt;Structured error logging&lt;/li&gt;
&lt;li&gt;Monitoring integration recommended&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;SEO Optimization&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Proper lastModified dates&lt;/li&gt;
&lt;li&gt;Appropriate priority settings&lt;/li&gt;
&lt;li&gt;Consistent language codes&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Next.js Sitemap API proves capable of handling large-scale multilingual sites effectively. The key to success lies in implementing proper caching strategies and error handling, enabling a balance between performance and maintainability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Resources
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/s4yuba/implementing-multilingual-sitemap-with-next-intl-in-nextjs-app-router-1354"&gt;Implementing Multilingual Sitemap with next-intl in Next.js App Router&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://nextjs.org/docs/app/api-reference/file-conventions/metadata/sitemap" rel="noopener noreferrer"&gt;Next.js Sitemap API Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/search/docs/crawling-indexing/sitemaps/build-sitemap" rel="noopener noreferrer"&gt;Google Search Central - Build and submit a sitemap&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control" rel="noopener noreferrer"&gt;Understanding Cache-Control Headers&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>sitemap</category>
      <category>nextjs</category>
    </item>
    <item>
      <title>Resolving Duplicate Key Issues in React Infinite Scroll with MongoDB Sort Behavior</title>
      <dc:creator>Oikon</dc:creator>
      <pubDate>Fri, 07 Feb 2025 12:37:22 +0000</pubDate>
      <link>https://dev.to/oikon/resolving-duplicate-key-issues-in-react-infinite-scroll-with-mongodb-sort-behavior-5fmc</link>
      <guid>https://dev.to/oikon/resolving-duplicate-key-issues-in-react-infinite-scroll-with-mongodb-sort-behavior-5fmc</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;While implementing infinite scroll functionality using React and MongoDB, I encountered an issue where data was duplicating at pagination boundaries. This article explores the cause of this problem, which stems from MongoDB's sorting behavior, and presents a concrete solution using the &lt;code&gt;_id&lt;/code&gt; field.&lt;/p&gt;

&lt;h2&gt;
  
  
  Target Audience
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Developers working with React and MongoDB applications&lt;/li&gt;
&lt;li&gt;Those implementing or planning to implement infinite scroll/pagination&lt;/li&gt;
&lt;li&gt;Anyone interested in understanding database sorting behaviors&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;p&gt;MongoDB's sorting behavior can lead to inconsistent ordering of documents with identical sort values. This causes key duplication warnings in React infinite scroll implementations. The solution involves adding the &lt;code&gt;_id&lt;/code&gt; field as a secondary sort key.&lt;/p&gt;

&lt;h2&gt;
  
  
  Development Environment
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- React 18.x
- MongoDB 8.0.0
- MongoDB Node.js Driver 6.9.0
- TypeScript 5.x
- Node.js 23.5.0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Problem Details
&lt;/h2&gt;

&lt;p&gt;When querying a MongoDB Collection with a large dataset using filters, duplicate data appeared in the infinite scroll display. Specifically, the last item from the first fetch overlapped with the first item from the second fetch.&lt;/p&gt;

&lt;h3&gt;
  
  
  Warning Message
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Warning: Encountered two children with the same key, `.$xxxxxxxxxxxx`. 
Keys should be unique so that components maintain their identity across updates. 
Non-unique keys may cause children to be duplicated and/or omitted — the behavior 
is unsupported and could change in a future version.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Reproduction Conditions
&lt;/h3&gt;

&lt;p&gt;The issue occurs when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MongoDB query includes filter conditions&lt;/li&gt;
&lt;li&gt;Sorting is in ascending order&lt;/li&gt;
&lt;li&gt;Retrieving data beyond the first page&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Problematic Code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Backend: MongoDB query&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sortObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;sortBy&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;asc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sortObject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lean&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// Frontend: React component&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;loadMore&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetchItems&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;items&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="nx"&gt;prev&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;items&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
    &lt;span class="nx"&gt;page&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}));&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Root Cause Analysis
&lt;/h2&gt;

&lt;h3&gt;
  
  
  MongoDB Sorting Behavior Characteristics
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Documents with identical sort values don't maintain consistent ordering&lt;/li&gt;
&lt;li&gt;When combined with pagination (&lt;code&gt;skip&lt;/code&gt; and &lt;code&gt;limit&lt;/code&gt;), the same document might appear on different pages&lt;/li&gt;
&lt;li&gt;This results in React displaying items with duplicate keys&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Solution
&lt;/h2&gt;

&lt;p&gt;Add &lt;code&gt;_id&lt;/code&gt; as a secondary sort key.&lt;br&gt;
Reference: &lt;a href="https://www.mongodb.com/docs/manual/reference/method/cursor.sort/" rel="noopener noreferrer"&gt;MongoDB Documentation: sort()&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Modified MongoDB Query
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;sortObject&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;sortBy&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;order&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;asc&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;_id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;  &lt;span class="c1"&gt;// Add _id as a secondary sort key&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;items&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Collection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;query&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;sortObject&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;skip&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;lean&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;exec&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why This Works
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;The &lt;code&gt;_id&lt;/code&gt; field in MongoDB guarantees uniqueness&lt;/li&gt;
&lt;li&gt;When primary sort keys have equal values, &lt;code&gt;_id&lt;/code&gt; ordering ensures consistent results&lt;/li&gt;
&lt;li&gt;This prevents pagination duplication&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Technical Analysis
&lt;/h2&gt;

&lt;h3&gt;
  
  
  MongoDB Sort Behavior
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;By default, the order of documents with identical sort values is indeterminate&lt;/li&gt;
&lt;li&gt;This behavior becomes more pronounced in distributed systems and sharding scenarios&lt;/li&gt;
&lt;li&gt;Stable sorting requires including a unique value in the sort keys&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;When implementing infinite scroll with MongoDB, sorting behavior can cause issues in these scenarios:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Sort fields contain duplicate values&lt;/li&gt;
&lt;li&gt;Pagination boundaries in large datasets&lt;/li&gt;
&lt;li&gt;Multiple filter condition combinations&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Utilizing the &lt;code&gt;_id&lt;/code&gt; field as a secondary sort key enables stable sort results and clean infinite scroll implementation.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://www.mongodb.com/docs/manual/reference/method/cursor.sort/" rel="noopener noreferrer"&gt;MongoDB Documentation: sort()&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://reactjs.org/docs/lists-and-keys.html" rel="noopener noreferrer"&gt;React Documentation: Lists and Keys&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>mongodb</category>
      <category>programming</category>
      <category>webdev</category>
      <category>react</category>
    </item>
    <item>
      <title>SEO and i18n Implementation Guide for Next.js App Router: Dynamic Metadata and Internationalization</title>
      <dc:creator>Oikon</dc:creator>
      <pubDate>Wed, 05 Feb 2025 13:41:08 +0000</pubDate>
      <link>https://dev.to/oikon/seo-and-i18n-implementation-guide-for-nextjs-app-router-dynamic-metadata-and-internationalization-3eol</link>
      <guid>https://dev.to/oikon/seo-and-i18n-implementation-guide-for-nextjs-app-router-dynamic-metadata-and-internationalization-3eol</guid>
      <description>&lt;p&gt;This article will provide practical implementation methods for optimizing SEO in internationalized (i18n) web applications using Next.js 14's App Router and Next-intl. We'll focus on metadata configuration for dynamically generated pages and multilingual support, using an e-commerce site as a concrete example.&lt;/p&gt;

&lt;h2&gt;
  
  
  Target Audience
&lt;/h2&gt;

&lt;p&gt;This guide is for developers who:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Have basic understanding of Next.js App Router&lt;/li&gt;
&lt;li&gt;Know TypeScript fundamentals&lt;/li&gt;
&lt;li&gt;Have basic SEO knowledge&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Development Environment
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"next"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^14.2.22"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"next-intl"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^3.26.3"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"react"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^18"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"typescript"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"^5"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  1. Project Structure
&lt;/h2&gt;

&lt;h3&gt;
  
  
  1.1 Directory Layout
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;src/
  ├── app/
  │   └── [locale]/
  │       └── product/
  │           └── [id]/
  │               ├── page.tsx
  │               └── layout.tsx
  ├── lib/
  │   └── metadata/
  │       └── productMetadata.ts
  ├── api/
  │   └── model/
  │       └── Product.ts
  └── i18n/
  │   ├── routing.ts
  │
  └── messages/
      ├── en.json
      └── ja.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1.2 Implementing Internationalized Routing
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/i18n/routing.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;defineRouting&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next-intl/routing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createNavigation&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next-intl/navigation&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routing&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;defineRouting&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;locales&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;ja&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;defaultLocale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Link&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;redirect&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;usePathname&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;useRouter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createNavigation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;routing&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  1.3 Product Data Type Definition
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/api/model/Product.ts&lt;/span&gt;
&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="kr"&gt;interface&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nl"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;code&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;category&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nl"&gt;manufacturer&lt;/span&gt;&lt;span class="p"&gt;?:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;description&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;images&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;small&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nl"&gt;large&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="nl"&gt;price&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="nl"&gt;stock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;number&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Dynamic Metadata Generation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  2.1 Implementing Metadata Generation Logic
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// src/lib/metadata/productMetadata.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Metadata&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;getTranslations&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;next-intl/server&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;Product&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/api/model/Product&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;routing&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/i18n/routing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generateProductMetadata&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="nx"&gt;productDataPromise&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Product&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;Metadata&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;productData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;t&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nb"&gt;Promise&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;all&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
    &lt;span class="nx"&gt;productDataPromise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;getTranslations&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;metadataProduct&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt;
  &lt;span class="p"&gt;]);&lt;/span&gt;

  &lt;span class="c1"&gt;// SEO optimization: Information structuring&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;descriptionParts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;productData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;productData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; #&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;productData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;code&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;productData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;manufacturer&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;manufacturedBy&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)}${&lt;/span&gt;&lt;span class="nx"&gt;productData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;manufacturer&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nf"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;checkPrice&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;description&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;descriptionParts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt; | &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="c1"&gt;// Dynamic keyword generation&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;productSpecificKeywords&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
    &lt;span class="nx"&gt;productData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;productData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;productData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;manufacturer&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;productData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;price&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;productData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;stock&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;productData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;products&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;
  &lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;baseKeywords&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;keywords&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;allKeywords&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[...&lt;/span&gt;&lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;([...&lt;/span&gt;&lt;span class="nx"&gt;productSpecificKeywords&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nx"&gt;baseKeywords&lt;/span&gt;&lt;span class="p"&gt;])];&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;productData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; | &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;productData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; | &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;siteTitle&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;keywords&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;allKeywords&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;join&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;, &lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;metadataBase&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;https://example.com&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;

    &lt;span class="na"&gt;alternates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;canonical&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/product/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;productData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;x-default&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`/en/product/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;productData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromEntries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
          &lt;span class="nx"&gt;routing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;locales&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/product/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;productData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
        &lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;

    &lt;span class="na"&gt;openGraph&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;website&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;siteName&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;t&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;siteTitle&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;title&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;productData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt; | &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;productData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;category&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;description&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;alternateLocale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;routing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;locales&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;l&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
      &lt;span class="na"&gt;images&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;productData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;images&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;large&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;productData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;images&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;large&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;width&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1200&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;height&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;630&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;alt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;productData&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;undefined&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
    &lt;span class="na"&gt;robots&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;index&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;follow&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2.2 Translation File Setup
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;messages/en.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"metadataProduct"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"siteTitle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Example Store"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"manufacturedBy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Manufactured by"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"checkPrice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Check price and availability"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"stock"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"stock"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"products"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"products"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"keywords"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"online store, ecommerce, shopping, price comparison, stock check, product reviews, online shopping"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="err"&gt;//&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;messages/ja.json&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"metadataProduct"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"siteTitle"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Example Store"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"manufacturedBy"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"製造元"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"checkPrice"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"価格と在庫状況をチェック"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"価格"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"stock"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"在庫"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"products"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"商品"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="nl"&gt;"keywords"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"オンラインストア, eコマース, 通販, 価格比較, 在庫確認, 商品レビュー, オンラインショッピング"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2.3 Page Component Implementation
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/[locale]/product/[id]/page.tsx&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;generateProductMetadata&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/lib/metadata/productMetadata&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;cache&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;react&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;notFound&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next/navigation&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getProductDataCached&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`/api/products/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;notFound&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;generateMetadata&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; 
  &lt;span class="nx"&gt;params&lt;/span&gt; 
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="nl"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="nl"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;productDataPromise&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;getProductDataCached&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;generateProductMetadata&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productDataPromise&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;ProductPage&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; 
  &lt;span class="nx"&gt;params&lt;/span&gt; 
&lt;span class="p"&gt;}:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
  &lt;span class="nl"&gt;params&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; 
&lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;productData&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;getProductDataCached&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;params&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="c1"&gt;// Page content implementation&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. SEO Optimization Key Points
&lt;/h2&gt;

&lt;h3&gt;
  
  
  3.1 Metadata Structuring
&lt;/h3&gt;

&lt;p&gt;When structuring metadata, consider:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Title Optimization&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Order information by importance&lt;/li&gt;
&lt;li&gt;Use pipes (|) for proper separation&lt;/li&gt;
&lt;li&gt;Include site name for brand recognition&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Description Structuring&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clear information segmentation&lt;/li&gt;
&lt;li&gt;Include only necessary information&lt;/li&gt;
&lt;li&gt;Match search intent&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Keyword Optimization&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Combine dynamic and static keywords&lt;/li&gt;
&lt;li&gt;Consider search patterns&lt;/li&gt;
&lt;li&gt;Natural keyword placement&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  3.2 Multilingual Considerations
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;URL Structure Design&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Include language codes&lt;/li&gt;
&lt;li&gt;Set proper canonical URLs&lt;/li&gt;
&lt;li&gt;Configure x-default&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Content Optimization&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Language-appropriate descriptions&lt;/li&gt;
&lt;li&gt;Cultural considerations&lt;/li&gt;
&lt;li&gt;Proper keyword translation&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  3.3 OpenGraph Configuration
&lt;/h3&gt;

&lt;p&gt;For OpenGraph settings:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Basic Configuration&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Choose appropriate type settings&lt;/li&gt;
&lt;li&gt;Maintain siteName and title consistency&lt;/li&gt;
&lt;li&gt;Optimize descriptions&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Image Handling&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Set appropriate sizes and ratios&lt;/li&gt;
&lt;li&gt;Configure alt attributes&lt;/li&gt;
&lt;li&gt;Handle missing images gracefully&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  4. Performance Optimization
&lt;/h2&gt;

&lt;h3&gt;
  
  
  4.1 Data Fetching Optimization
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Utilizing Cache
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;   &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;getProductDataCached&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;cache&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
     &lt;span class="c1"&gt;// Data fetching logic&lt;/span&gt;
   &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Prevent duplicate requests&lt;/li&gt;
&lt;li&gt;Improve response time&lt;/li&gt;
&lt;li&gt;Ensure consistent data&lt;/li&gt;
&lt;/ul&gt;

&lt;ol&gt;
&lt;li&gt;Error Handling

&lt;ul&gt;
&lt;li&gt;Display 404 pages appropriately&lt;/li&gt;
&lt;li&gt;Maintain user experience&lt;/li&gt;
&lt;li&gt;Ensure crawlability&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  4.2 Rendering Optimization
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;Separate Metadata Generation&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Clear logic separation&lt;/li&gt;
&lt;li&gt;Improve reusability&lt;/li&gt;
&lt;li&gt;Enhance maintainability&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Optimize Async Processing&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Parallel processing for speed&lt;/li&gt;
&lt;li&gt;Efficient resource usage&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;We've covered key implementation points for SEO and internationalization in Next.js App Router:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dynamic metadata generation implementation&lt;/li&gt;
&lt;li&gt;Multilingual support considerations and optimization&lt;/li&gt;
&lt;li&gt;SEO best practices&lt;/li&gt;
&lt;li&gt;Performance optimization techniques&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These implementations enable building SEO-optimized multilingual web applications effectively.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nextjs.org/docs/app/building-your-application/optimizing/metadata" rel="noopener noreferrer"&gt;Next.js Documentation - Metadata&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://next-intl-docs.vercel.app/" rel="noopener noreferrer"&gt;next-intl Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://developers.google.com/search/docs/fundamentals/seo-starter-guide" rel="noopener noreferrer"&gt;Google Search Central - SEO Starter Guide&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>nextjs</category>
      <category>programming</category>
      <category>react</category>
      <category>web</category>
    </item>
    <item>
      <title>Implementing Multilingual Sitemap with next-intl in Next.js App Router</title>
      <dc:creator>Oikon</dc:creator>
      <pubDate>Thu, 30 Jan 2025 12:49:06 +0000</pubDate>
      <link>https://dev.to/oikon/implementing-multilingual-sitemap-with-next-intl-in-nextjs-app-router-1354</link>
      <guid>https://dev.to/oikon/implementing-multilingual-sitemap-with-next-intl-in-nextjs-app-router-1354</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;This article describes the journey of implementing a multilingual sitemap in a Next.js App Router project. Initially attempting to use next-sitemap, we ultimately switched to the App Router's built-in sitemap generation functionality. Here's what we learned along the way.&lt;/p&gt;

&lt;h2&gt;
  
  
  Development Environment
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- Next.js 14.x (App Router)
- TypeScript 5.x
- next-intl 3.x
- next-sitemap 4.x
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Sitemap generation supporting multiple languages (/en, /ja, etc.)&lt;/li&gt;
&lt;li&gt;Proper alternate links configuration for each language&lt;/li&gt;
&lt;li&gt;SEO-compliant XML format&lt;/li&gt;
&lt;li&gt;Appropriate priority and update frequency settings for pages&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Initial Implementation with next-sitemap and Its Challenges
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Initial Setup
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// next-sitemap.config.js&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;siteUrl&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;generateRobotsTxt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;exclude&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/_not-found&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/404&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/500&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
  &lt;span class="na"&gt;generateIndexSitemap&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;

  &lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;changefreq&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;daily&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;lastmod&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nf"&gt;toISOString&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Technical Issues Encountered
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Alternate Links Generation Error&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The issue where &lt;code&gt;/en/about&lt;/code&gt; incorrectly follows &lt;code&gt;/ja/about&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="c"&gt;&amp;lt;!-- Incorrect generation example --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;url&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;loc&amp;gt;&lt;/span&gt;https://example.com/en/about&lt;span class="nt"&gt;&amp;lt;/loc&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;xhtml:link&lt;/span&gt; &lt;span class="na"&gt;rel=&lt;/span&gt;&lt;span class="s"&gt;"alternate"&lt;/span&gt; &lt;span class="na"&gt;hreflang=&lt;/span&gt;&lt;span class="s"&gt;"ja"&lt;/span&gt; 
    &lt;span class="na"&gt;href=&lt;/span&gt;&lt;span class="s"&gt;"https://example.com/ja/about/en/about"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/url&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Sitemap Index Structure Issues
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="UTF-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;sitemapindex&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"http://www.sitemaps.org/schemas/sitemap/0.9"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
&lt;span class="c"&gt;&amp;lt;!-- Empty index generation --&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/sitemapindex&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Troubleshooting Process
&lt;/h2&gt;

&lt;p&gt;During &lt;code&gt;npm run build&lt;/code&gt;, we can observe static (SSG) and dynamic page generation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;Route &lt;span class="o"&gt;(&lt;/span&gt;app&lt;span class="o"&gt;)&lt;/span&gt;
┌ ○ /_not-found 
├ ● /[locale]   
├   ├ /en
├   └ /ja
├ ● /[locale]/about   
├   ├ /en/about
├   └ /ja/about
├ ƒ /[locale]/blog/[id]
├ ● /[locale]/contact
├   ├ /en/contact
├   └ /ja/contact
└ ● /[locale]/products
    ├ /en/products
    └ /ja/products

○  &lt;span class="o"&gt;(&lt;/span&gt;Static&lt;span class="o"&gt;)&lt;/span&gt;   prerendered as static content
●  &lt;span class="o"&gt;(&lt;/span&gt;SSG&lt;span class="o"&gt;)&lt;/span&gt;      prerendered as static HTML &lt;span class="o"&gt;(&lt;/span&gt;uses getStaticProps&lt;span class="o"&gt;)&lt;/span&gt;
ƒ  &lt;span class="o"&gt;(&lt;/span&gt;Dynamic&lt;span class="o"&gt;)&lt;/span&gt;  server-rendered on demand
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Attempted Solutions
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Transform Approach
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// next-sitemap.config.js&lt;/span&gt;
&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;transform&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;parts&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;split&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Boolean&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;locale&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;parts&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ja&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nf"&gt;includes&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;siteUrl&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;changefreq&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;weekly&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;alternateRefs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[{&lt;/span&gt;
        &lt;span class="na"&gt;href&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;siteUrl&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ja&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="na"&gt;hreflang&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;locale&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ja&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
      &lt;span class="p"&gt;}]&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach failed to resolve the issue of redundant paths in alternateRefs URLs.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Additional Paths Approach
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;module&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;exports&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;additionalPaths&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;config&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;urls&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[];&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;locales&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;en&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;ja&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/about&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/contact&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/products&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="nx"&gt;locales&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(({&lt;/span&gt; &lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;priority&lt;/span&gt; &lt;span class="p"&gt;})&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;push&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
          &lt;span class="na"&gt;loc&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;path&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;changefreq&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;weekly&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="nx"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
          &lt;span class="na"&gt;alternateRefs&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="cm"&gt;/* ... */&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
      &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;urls&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This approach required manual URL management, leading to maintenance issues.&lt;/p&gt;

&lt;h2&gt;
  
  
  Solution Using App Router's Built-in Functionality
&lt;/h2&gt;

&lt;p&gt;Inspired by &lt;a href="https://github.com/amannn/next-intl/blob/main/examples/example-app-router/src/app/sitemap.ts" rel="noopener noreferrer"&gt;next-intl's example implementation&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// app/sitemap.ts&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;MetadataRoute&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;next&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;
&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;routing&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@/i18n/routing&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;host&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;NEXT_PUBLIC_HOST&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;http://localhost:3000&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;export&lt;/span&gt; &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;sitemap&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="nx"&gt;MetadataRoute&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Sitemap&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;baseUrl&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;https://example.com&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;

    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;''&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/about&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/contact&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;/products&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="na"&gt;priority&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.8&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;]&lt;/span&gt;

    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;routes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;flatMap&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt;
        &lt;span class="nx"&gt;routing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;locales&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt;
            &lt;span class="na"&gt;url&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;locale&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;route&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="na"&gt;alternates&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="na"&gt;languages&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Object&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;fromEntries&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
                    &lt;span class="nx"&gt;routing&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;locales&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;map&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="nx"&gt;altLocale&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;altLocale&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;host&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;altLocale&lt;/span&gt;&lt;span class="p"&gt;}${&lt;/span&gt;&lt;span class="nx"&gt;route&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;route&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
                &lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="p"&gt;},&lt;/span&gt;
        &lt;span class="p"&gt;}))&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Place this in &lt;code&gt;src/app/sitemap.ts&lt;/code&gt;, and Next.js will automatically generate the &lt;code&gt;sitemap.xml&lt;/code&gt;. You can verify the generated sitemap by accessing &lt;code&gt;localhost:3000/sitemap.xml&lt;/code&gt; in development.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparison of Implementation Approaches
&lt;/h2&gt;

&lt;h3&gt;
  
  
  next-sitemap
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Automatic robots.txt generation&lt;/li&gt;
&lt;li&gt;Rich configuration options&lt;/li&gt;
&lt;li&gt;Sitemap index generation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complex configuration for multilingual support&lt;/li&gt;
&lt;li&gt;Compatibility issues with App Router&lt;/li&gt;
&lt;li&gt;Difficult debugging process&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  App Router Built-in Functionality
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Advantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Full TypeScript support&lt;/li&gt;
&lt;li&gt;Easy integration with App Router&lt;/li&gt;
&lt;li&gt;Simple implementation structure&lt;/li&gt;
&lt;li&gt;Straightforward debugging&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Disadvantages:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requires separate robots.txt implementation&lt;/li&gt;
&lt;li&gt;Limited configuration options&lt;/li&gt;
&lt;li&gt;Lacks sitemap index functionality&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Implementation Decision Criteria
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Choose next-sitemap when:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Using Pages Router&lt;/li&gt;
&lt;li&gt;Complex sitemap requirements&lt;/li&gt;
&lt;li&gt;Single language site&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Choose App Router Built-in when:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Using App Router&lt;/li&gt;
&lt;li&gt;Multilingual site requirements&lt;/li&gt;
&lt;li&gt;TypeScript-focused development&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;For multilingual sitemap implementation in Next.js App Router, the built-in functionality proves to be the optimal solution. The TypeScript support and implementation simplicity significantly enhance development efficiency. For SEO requirements in multilingual sites, the App Router's built-in functionality is recommended.&lt;/p&gt;

&lt;h2&gt;
  
  
  References
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://nextjs.org/docs" rel="noopener noreferrer"&gt;Next.js App Router Documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/iamvishnusankar/next-sitemap" rel="noopener noreferrer"&gt;next-sitemap GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/amannn/next-intl/blob/main/examples/example-app-router/src/app/sitemap.ts" rel="noopener noreferrer"&gt;next-intl Example Implementation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>nextjs</category>
      <category>webdev</category>
      <category>programming</category>
      <category>react</category>
    </item>
  </channel>
</rss>
