<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[HEROPY.DEV]]></title><description><![CDATA[HEROPY.DEV is a tech blog that shares web development knowledge.]]></description><link>https://www.heropy.dev/en</link><generator>RSS for Node</generator><lastBuildDate>Wed, 21 Oct 2026 15:36:00 GMT</lastBuildDate><atom:link href="https://www.heropy.dev/en/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><item><title><![CDATA[Claude Code Essentials]]></title><description><![CDATA[Claude Code is a terminal-based AI coding tool developed by Anthropic. From installation and sign-in to CLAUDE.md, permission modes, context management, MCP connectors, browser and computer control, Hooks, Skills, agents, Remote Control, and plugins, this post covers the core features with real screenshots and diagrams.]]></description><link>https://www.heropy.dev/en/p/4weJmr</link><guid isPermaLink="false">/en/p/4weJmr</guid><category><![CDATA[AI]]></category><category><![CDATA[Claude Code]]></category><category><![CDATA[Anthropic]]></category><category><![CDATA[CLI]]></category><category><![CDATA[Agent Skills]]></category><category><![CDATA[MCP]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 14:47:25 GMT</pubDate></item><item><title><![CDATA[Fixing the Claude Code API Key Prompt That No Longer Appears]]></title><description><![CDATA[<p>To use Claude Code with an API key instead of signing in with a personal account, you register the key in the <code>ANTHROPIC_API_KEY</code> environment variable.<br>When you run the <code>claude</code> command in a terminal with the key registered, a confirmation screen asks whether you want to use that API key.</p>
<p><img src="https://somwpkzlplaovldnfahk.supabase.co/storage/v1/object/public/heropy.dev_shorts/97/0E2t" alt="Confirming whether to use the API key" title="--970x422x0.5"></p>
<p>To use the API key, you need to select <code>Yes</code>, but the default selection is <code>No (recommended)</code>, so if you press Enter without reading the screen carefully, you end up choosing not to use the API key.<br>It works this way because signing in with an account is the recommended path, but if you meant to use an API key, it is the opposite of what you wanted.</p>
<p>Even if you notice the mistake, quit Claude Code, and run it again, this confirmation screen no longer appears.<br>That is because your choice is recorded in a file, and Claude Code does not ask again about an API key that already has a record.<br>The record is stored in the <code>customApiKeyResponses</code> property of the <code>.claude.json</code> file in your home directory.</p>
<ul>
<li>macOS: <code>~/.claude.json</code></li>
<li>Windows: <code>C:\Users\username\.claude.json</code></li>
</ul>
<pre><code class="language-json">{
  &quot;customApiKeyResponses&quot;: {
    &quot;approved&quot;: [],
    &quot;rejected&quot;: [&quot;AbCdEfGhIjKlMnOpQrSt&quot;]
  }
}
</code></pre>
<p>The values in the arrays are not the full API keys but the last 20 characters of each key.<br>They are identifiers that tell which API key a response belongs to, and they also keep the full key from being stored in this file as plain text.</p>
<p>When Claude Code starts, it takes the last 20 characters of the key in the environment variable, compares them with the two arrays, and decides on one of three states.</p>
<table>
<thead>
<tr>
<th>State</th>
<th>Condition</th>
<th>Behavior</th>
</tr>
</thead>
<tbody><tr>
<td>Approved</td>
<td>In the <code>approved</code> array</td>
<td>Uses the API key without asking</td>
</tr>
<tr>
<td>Rejected</td>
<td>In the <code>rejected</code> array</td>
<td>Ignores the API key without asking</td>
</tr>
<tr>
<td>Undecided</td>
<td>In neither array</td>
<td>Shows the confirmation screen</td>
</tr>
</tbody></table>
<p>The confirmation screen appears only in the undecided state.<br>If you select <code>No</code> by mistake, the API key goes into <code>rejected</code> and the state becomes rejected, so the confirmation screen does not appear and the API key is not used.<br>This record stays even if you log out or reinstall Claude Code.</p>
<p>So if you remove just that value from the <code>rejected</code> array, the state goes back to undecided, and the confirmation screen appears the next time you run Claude Code.<br>If the array has only one value, you can leave it as an empty array.</p>
<pre><code class="language-json">{
  &quot;customApiKeyResponses&quot;: {
    &quot;approved&quot;: [],
    &quot;rejected&quot;: []
  }
}
</code></pre>
<blockquote><p><code>~/.claude.json</code> is a file that Claude Code updates while it is running.<br>Quit every running Claude Code session before you edit it, so your changes are not overwritten.</p>
</blockquote><p>There is also a way to fix this without editing the file directly.<br>With the <code>ANTHROPIC_API_KEY</code> environment variable registered, sign in with an account such as a personal subscription, then go to <code>/config</code> and change <code>Use custom API key</code> from <code>false</code> to <code>true</code>, and the API key moves from <code>rejected</code> to <code>approved</code>.<br>Then log out again and try using the API key.</p>
<p><img src="https://somwpkzlplaovldnfahk.supabase.co/storage/v1/object/public/heropy.dev_shorts/97/qIr7" alt="The Use custom API key option needs to be turned on" title="--984x342x0.5"></p>
]]></description><link>https://www.heropy.dev/en/s/97</link><guid isPermaLink="false">/en/s/97</guid><category><![CDATA[Claude Code]]></category><category><![CDATA[API]]></category><category><![CDATA[CLI]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:37 GMT</pubDate></item><item><title><![CDATA[A Summary of Basic Terminal Commands]]></title><description><![CDATA[<p>Here are the basic terminal commands you&#39;ll use often in macOS (zsh/bash), Windows PowerShell, and CMD.</p>
<table>
<thead>
<tr>
<th>Purpose</th>
<th>macOS</th>
<th>PowerShell</th>
<th>CMD</th>
</tr>
</thead>
<tbody><tr>
<td>Show the current location</td>
<td><code>pwd</code></td>
<td><code>pwd</code></td>
<td><code>cd</code></td>
</tr>
<tr>
<td>List items</td>
<td><code>ls -al</code></td>
<td><code>ls</code> / <code>dir</code></td>
<td><code>dir</code></td>
</tr>
<tr>
<td>Go to a specific folder</td>
<td><code>cd ~/apple/banana</code></td>
<td><code>cd $HOME\apple\banana</code></td>
<td><code>cd /d C:\apple\banana</code></td>
</tr>
<tr>
<td>Go to the parent folder</td>
<td><code>cd ..</code></td>
<td><code>cd ..</code></td>
<td><code>cd ..</code></td>
</tr>
<tr>
<td>Go to the home folder</td>
<td><code>cd ~</code></td>
<td><code>cd ~</code></td>
<td><code>cd %USERPROFILE%</code></td>
</tr>
<tr>
<td>Clear the screen</td>
<td><code>clear</code></td>
<td><code>cls</code></td>
<td><code>cls</code></td>
</tr>
<tr>
<td>Create a folder</td>
<td><code>mkdir -p apple/banana</code></td>
<td><code>mkdir apple\banana</code></td>
<td><code>mkdir apple\banana</code></td>
</tr>
<tr>
<td>Create an empty file</td>
<td><code>touch cherry.md</code></td>
<td><code>ni cherry.md</code></td>
<td><code>type nul &gt; cherry.md</code></td>
</tr>
<tr>
<td>Copy</td>
<td><code>cp -r apple banana</code></td>
<td><code>cp -r apple banana</code></td>
<td><code>xcopy /E /I apple banana</code></td>
</tr>
<tr>
<td>Move and rename</td>
<td><code>mv apple banana</code></td>
<td><code>mv apple banana</code></td>
<td><code>move apple banana</code></td>
</tr>
<tr>
<td>Delete a folder</td>
<td><code>rm -rf apple</code></td>
<td><code>rm -r -fo apple</code></td>
<td><code>rmdir /s /q apple</code></td>
</tr>
<tr>
<td>Print contents</td>
<td><code>cat cherry.md</code></td>
<td><code>cat cherry.md</code></td>
<td><code>type cherry.md</code></td>
</tr>
<tr>
<td>Command location</td>
<td><code>which claude</code></td>
<td><code>gcm claude</code></td>
<td><code>where claude</code></td>
</tr>
</tbody></table>
<blockquote><p>If a path contains spaces, wrap it in quotes, like <code>cd &quot;C:\My Project&quot;</code>.<br><code>type nul &gt; cherry.md</code> erases all the contents of a file with the same name if it already exists, leaving an empty file.</p>
</blockquote><p><strong>What the path symbols mean:</strong></p>
<table>
<thead>
<tr>
<th>Symbol</th>
<th>Meaning</th>
</tr>
</thead>
<tbody><tr>
<td><code>~</code></td>
<td>Home folder (macOS, PowerShell)</td>
</tr>
<tr>
<td><code>$HOME</code></td>
<td>Variable that holds the home folder path (PowerShell)</td>
</tr>
<tr>
<td><code>%USERPROFILE%</code></td>
<td>Environment variable that holds the home folder path (CMD)</td>
</tr>
<tr>
<td><code>..</code></td>
<td>Parent folder of the current location</td>
</tr>
</tbody></table>
<p><strong>What the flags mean:</strong></p>
<p>Flags start with <code>-</code> in macOS and PowerShell, and with <code>/</code> in CMD.<br>In macOS, you can combine <code>ls -a -l</code> into <code>ls -al</code>.</p>
<table>
<thead>
<tr>
<th>Flag</th>
<th>Example</th>
<th>Meaning</th>
</tr>
</thead>
<tbody><tr>
<td><code>-a</code></td>
<td><code>ls -a</code></td>
<td>Shows all items, including hidden files</td>
</tr>
<tr>
<td><code>-l</code></td>
<td><code>ls -l</code></td>
<td>Shows details (Long) such as permissions, size, and modification date</td>
</tr>
<tr>
<td><code>-p</code></td>
<td><code>mkdir -p apple/banana</code></td>
<td>Also creates the intermediate folders (Parents) if they don&#39;t exist</td>
</tr>
<tr>
<td><code>-r</code></td>
<td><code>cp -r</code>, <code>rm -rf</code></td>
<td>Processes everything inside the folder recursively</td>
</tr>
<tr>
<td><code>-f</code></td>
<td><code>rm -rf</code></td>
<td>Deletes forcibly without asking for confirmation</td>
</tr>
<tr>
<td><code>-fo</code></td>
<td><code>rm -r -fo</code></td>
<td>Forced deletion; in PowerShell, <code>-f</code> is ambiguous with other options, so it&#39;s shortened to <code>-fo</code></td>
</tr>
<tr>
<td><code>/d</code></td>
<td><code>cd /d C:\apple\banana</code></td>
<td>Needed to move to a drive other than the current drive</td>
</tr>
<tr>
<td><code>/E</code></td>
<td><code>xcopy /E /I apple banana</code></td>
<td>Copies all subfolders, including empty ones</td>
</tr>
<tr>
<td><code>/I</code></td>
<td><code>xcopy /E /I apple banana</code></td>
<td>Creates the destination folder if it doesn&#39;t exist, then copies</td>
</tr>
<tr>
<td><code>/s</code></td>
<td><code>rmdir /s /q apple</code></td>
<td>Deletes all subdirectories and files too</td>
</tr>
<tr>
<td><code>/q</code></td>
<td><code>rmdir /s /q apple</code></td>
<td>Quiet mode that doesn&#39;t ask for confirmation before deleting</td>
</tr>
</tbody></table>
<p><strong>Terminal shortcuts:</strong></p>
<table>
<thead>
<tr>
<th>Key</th>
<th>Action</th>
</tr>
</thead>
<tbody><tr>
<td><code>Tab</code></td>
<td>Autocomplete paths and commands</td>
</tr>
<tr>
<td><code>↑</code> / <code>↓</code></td>
<td>Recall previous commands</td>
</tr>
<tr>
<td><code>Ctrl + C</code></td>
<td>Stop the running command</td>
</tr>
</tbody></table>
]]></description><link>https://www.heropy.dev/en/s/92</link><guid isPermaLink="false">/en/s/92</guid><category><![CDATA[Terminal]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:37 GMT</pubDate></item><item><title><![CDATA[🚨 Urgent Update Advisory for React (Next.js) Server Components Security Vulnerabilities]]></title><description><![CDATA[<p>Serious security vulnerabilities related to React Server Components (RSC) have been found, and security patches are recommended!</p>
<ul>
<li><a href="https://nvd.nist.gov/vuln/detail/CVE-2025-55182">CVE-2025-55182</a></li>
<li><a href="https://www.cve.org/CVERecord?id=CVE-2025-55183">CVE-2025-55183</a></li>
<li><a href="https://www.cve.org/CVERecord?id=CVE-2025-55184">CVE-2025-55184</a></li>
<li><a href="https://nvd.nist.gov/vuln/detail/CVE-2025-66478">CVE-2025-66478</a></li>
<li><a href="https://www.cve.org/CVERecord?id=CVE-2025-67779">CVE-2025-67779</a></li>
</ul>
<p>These vulnerabilities carry the risk of leading to pre-authentication remote code execution (RCE) attacks, so every project on an affected version must update right away to the fixed versions below to prevent serious security incidents.</p>
<div class="table-wrap">
<table>
  <thead>
    <tr>
      <th>Product</th>
      <th>Affected versions</th>
      <th>Fixed version</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td rowspan="3">
        react-server-dom-parcel<br/>
        react-server-dom-webpack<br/>
        react-server-dom-turbopack
      </td>
      <td>19.0</td>
      <td>19.0.3</td>
    </tr>
    <tr>
      <td>19.1.0 - 19.1.1</td>
      <td>19.1.4</td>
    </tr>
    <tr>
      <td>19.2.0</td>
      <td>19.2.3</td>
    </tr>
    <tr>
      <td rowspan="8">next</td>
      <td>14.x, >=13.3</td>
      <td>14.2.35</td>
    </tr>
    <tr>
      <td>15.0.x</td>
      <td>15.0.7</td>
    </tr>
    <tr>
      <td>15.1.x</td>
      <td>15.1.11</td>
    </tr>
    <tr>
      <td>15.2.x</td>
      <td>15.2.8</td>
    </tr>
    <tr>
      <td>15.3.x</td>
      <td>15.3.8</td>
    </tr>
    <tr>
      <td>15.4.x</td>
      <td>15.4.10</td>
    </tr>
    <tr>
      <td>15.5.x</td>
      <td>15.5.9</td>
    </tr>
    <tr>
      <td>16.0.x</td>
      <td>16.0.10</td>
    </tr>
  </tbody>
</table>
</div>

<pre><code class="language-bash">npm update react-server-dom-webpack react-server-dom-parcel react-server-dom-turbopack
</code></pre>
<pre><code class="language-bash">npm i next@latest
# or
npx fix-react2shell-next
</code></pre>
<ul>
<li><a href="https://react.dev/blog/2025/12/11/denial-of-service-and-source-code-exposure-in-react-server-components">Denial of Service and Source Code Exposure in React Server Components</a></li>
<li><a href="https://nextjs.org/blog/security-update-2025-12-11">Next.js Security Update: December 11, 2025</a></li>
</ul>
]]></description><link>https://www.heropy.dev/en/s/86</link><guid isPermaLink="false">/en/s/86</guid><category><![CDATA[React]]></category><category><![CDATA[Next]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:36 GMT</pubDate></item><item><title><![CDATA[Fixing Development Server Access Issues Caused by the CSP Upgrade Insecure Requests Directive in Safari]]></title><description><![CDATA[<pre><code class="language-html">&lt;meta http-equiv=&quot;Content-Security-Policy&quot; content=&quot;upgrade-insecure-requests&quot; /&gt;
</code></pre>
<p><code>upgrade-insecure-requests</code> is a CSP (Content-Security-Policy) directive that tells the browser to automatically upgrade every HTTP request in a web page (images, scripts, APIs, and so on) to HTTPS.<br>Loading HTTP resources on a web page served over HTTPS can open security holes such as XSS, MITM, and data interception, so most browsers block these resources or show a mixed content warning.<br>Automatically converting HTTP resource requests to HTTPS is an easy way to solve this mixed content problem.</p>
<blockquote><p>Blocking mixed content with the <code>block-all-mixed-content</code> directive is deprecated, and it conflicts with the <code>upgrade-insecure-requests</code> directive.</p>
</blockquote><p>In a development environment, you usually use an HTTP address such as <code>http://localhost:5173</code>.<br>With the <code>upgrade-insecure-requests</code> directive, even a local development server like this would have to be redirected to HTTPS, but common browsers such as Chrome and Firefox make an exception so that HTTP requests still work.<br>Safari, however, is a well-known browser that makes no such exception and strictly tries to redirect HTTP requests to HTTPS.<br>So when <code>http://localhost</code> is redirected to <code>https://localhost</code>, you can no longer reach a local development server that does not support HTTPS.</p>
<p><img src="https://somwpkzlplaovldnfahk.supabase.co/storage/v1/object/public/heropy.dev_shorts/85/Q8mM" alt="The problem in the Safari browser" title="--1336x576"></p>
<p>A simple way to fix this is to remove the Upgrade Insecure Requests directive from your local development environment.<br>Apply the directive conditionally, for example with environment variables, so that it is only used in production.</p>
<p><strong>Vite configuration example</strong></p>
<p>Inject the CSP meta tag conditionally at build time.</p>
<pre><code class="language-bash">npm i -D vite-plugin-html
</code></pre>
<pre><code class="language-ts">import { defineConfig } from &#39;vite&#39;
import { createHtmlPlugin } from &#39;vite-plugin-html&#39;

const tags = []
if (process.env.NODE_ENV === &#39;development&#39;) {
  tags.push({
    tag: &#39;meta&#39;,
    attrs: {
      httpEquiv: &#39;Content-Security-Policy&#39;,
      content: &#39;upgrade-insecure-requests&#39;
    }
  })
}
export default defineConfig({
  plugins: [
    createHtmlPlugin({
      inject: { tags }
    })
  ]
})
</code></pre>
<p><strong>Next.js configuration example</strong></p>
<p>Add the CSP header to requests for every path.</p>
<pre><code class="language-ts">import type { NextConfig } from &#39;next&#39;

const nextConfig: NextConfig = {
  async headers() {
    return [
      {
        source: &#39;/:path*&#39;,
        headers: [
          {
            key: &#39;Content-Security-Policy&#39;,
            value: process.env.NODE_ENV === &#39;production&#39; ? &#39;upgrade-insecure-requests&#39; : &#39;&#39;
          }
        ]
      }
    ]
  }
}
export default nextConfig
</code></pre>
<p><strong>SvelteKit configuration example</strong></p>
<p>Add the CSP meta tag conditionally in the application.</p>
<pre><code class="language-svelte">&lt;script lang=&quot;ts&quot;&gt;
  import { dev } from &#39;$app/environment&#39;
&lt;/script&gt;

&lt;svelte:head&gt;
  {#if !dev}
    &lt;meta
      http-equiv=&quot;Content-Security-Policy&quot;
      content=&quot;upgrade-insecure-requests&quot; /&gt;
  {/if}
&lt;/svelte:head&gt;
</code></pre>
<p><strong>HTTPS development server example</strong></p>
<p>The first time you run the local Vite development server, you may be asked to enter your password, and a local certificate is installed on your system and browsers.<br>After that, you can access the server at <code>https://localhost</code>.</p>
<pre><code class="language-bash">npm i -D vite-plugin-mkcert
</code></pre>
<pre><code class="language-ts">import { defineConfig } from &#39;vite&#39;
import mkcert from &#39;vite-plugin-mkcert&#39;

export default defineConfig({
  plugins: [
    mkcert()
  ]
})
</code></pre>
]]></description><link>https://www.heropy.dev/en/s/85</link><guid isPermaLink="false">/en/s/85</guid><category><![CDATA[Safari]]></category><category><![CDATA[CSP]]></category><category><![CDATA[Vite]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:36 GMT</pubDate></item><item><title><![CDATA[An Example of Searching and Listing Movies with useQuery in TanStack Vue Query]]></title><description><![CDATA[<p>When you use TanStack Query in Vue, to handle the returned data reactively, pass a computed data reference (ComputedRef) as the options of the <code>useQuery</code> function.<br>Then changes in query options such as the query key (<code>queryKey</code>) and <code>enabled</code> are also tracked reactively.</p>
<pre><code class="language-vue">&lt;script setup lang=&quot;ts&quot;&gt;
import { ref, computed } from &#39;vue&#39;
import { useQuery, useQueryClient } from &#39;@tanstack/vue-query&#39;
import type { UseQueryOptions } from &#39;@tanstack/vue-query&#39;

type Movies = Movie[]
interface Movie {
  imdbID: string
  Title: string
  Poster: string
  Year: string
}

const inputText = ref(&#39;&#39;) // Bound to the input element, so it changes continuously
const searchText = ref(&#39;&#39;) // Changes only when you search
const queryOptions = computed(() =&gt; {
  return {
    queryKey: [&#39;movies&#39;, searchText.value],
    queryFn: async () =&gt; {
      const res = await fetch(`https://omdbapi.com?apikey=7035c60c&amp;s=${searchText.value}`)
      const { Search: movies = [] } = await res.json()
      return movies as Movies
    },
    staleTime: 1000 * 60 * 60, // Cache for 1 hour
    placeholderData: prev =&gt; prev, // Use the previous data as placeholder data (prevents flickering)
    enabled: !!searchText.value // Don&#39;t run if there&#39;s no search text
  } satisfies UseQueryOptions&lt;Movies&gt;
})
console.log(queryOptions) // ComputedRef
console.log(queryOptions.value) // Query option values

const queryClient = useQueryClient()
const { data, isFetching } = useQuery&lt;Movie[]&gt;(queryOptions) // Pass the ComputedRef object

async function fetchMovies() {
  searchText.value = inputText.value // Use the entered text as the search text
  if (!searchText.value.trim()) return
  // fetchQuery uses the cached data, or fetches new data if there&#39;s none!
  await queryClient.fetchQuery(queryOptions) // Pass the ComputedRef object
}
&lt;/script&gt;

&lt;template&gt;
  &lt;div&gt;
    &lt;input
      v-model=&quot;inputText&quot;
      @keydown.enter=&quot;fetchMovies&quot; /&gt;
    &lt;button @click=&quot;fetchMovies&quot;&gt;Search&lt;/button&gt;
  &lt;/div&gt;
  {{ isFetching ? &#39;Loading...&#39; : &#39;&#39; }}
  &lt;ul&gt;
    &lt;li
      v-for=&quot;movie in data&quot;
      :key=&quot;movie.imdbID&quot;&gt;
      {{ movie.Title }} ({{ movie.Year }})
    &lt;/li&gt;
  &lt;/ul&gt;
  &lt;RouterView /&gt;
&lt;/template&gt;
</code></pre>
]]></description><link>https://www.heropy.dev/en/s/83</link><guid isPermaLink="false">/en/s/83</guid><category><![CDATA[Vue]]></category><category><![CDATA[TanStack Query]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:36 GMT</pubDate></item><item><title><![CDATA[A Summary of TypeScript Configuration (tsconfig.json)]]></title><description><![CDATA[<h4>tsconfig.json</h4>
<p>The <code>tsconfig.json</code> file specifies how the TypeScript compiler converts your project to JS.</p>
<pre><code class="language-json">{
  &quot;files&quot;: [&quot;node_modules/my-library/index.ts&quot;],
  &quot;exclude&quot;: [&quot;node_modules&quot;, &quot;dist&quot;],
  &quot;include&quot;: [&quot;src/**/*&quot;],
  &quot;extends&quot;: &quot;config/base.json&quot;,
  &quot;compilerOptions&quot;: {}
}
</code></pre>
<table>
<thead>
<tr>
<th>Option</th>
<th>Priority</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td>files</td>
<td>1</td>
<td>List of individual files to compile (extensions required!)</td>
</tr>
<tr>
<td>exclude</td>
<td>2</td>
<td>List of file paths to exclude from compilation</td>
</tr>
<tr>
<td>include</td>
<td>3</td>
<td>List of file paths to compile<br>You can omit the <code>.ts</code>, <code>.tsx</code>, and <code>.d.ts</code> extensions, and <code>.js</code> and <code>.jsx</code> are added when <code>allowJS: true</code></td>
</tr>
<tr>
<td>extends</td>
<td>-</td>
<td>Another TS configuration to inherit from</td>
</tr>
<tr>
<td>compilerOptions</td>
<td>-</td>
<td>Specifies compiler options</td>
</tr>
</tbody></table>
<h5>CompilerOptions</h5>
<p>Here are the main options you can use in <code>CompilerOptions</code>.</p>
<pre><code class="language-json">{
  &quot;compilerOptions&quot;: {
    &quot;target&quot;: &quot;ES2015&quot;,
    &quot;module&quot;: &quot;ESNext&quot;,
    &quot;moduleResolution&quot;: &quot;Node&quot;,
    &quot;jsx&quot;: &quot;preserve&quot;,
    &quot;strict&quot;: true,
    &quot;esModuleInterop&quot;: true,
    &quot;lib&quot;: [&quot;ESNext&quot;, &quot;DOM&quot;]
  }
}
</code></pre>
<table>
<thead>
<tr>
<th>Option</th>
<th>Default</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td>target</td>
<td><code>&quot;ES3&quot;</code></td>
<td>Specifies the ES version to compile to.</td>
</tr>
<tr>
<td>lib</td>
<td>-</td>
<td>Specifies the libraries to use in compilation.</td>
</tr>
<tr>
<td>module</td>
<td><code>&quot;CommonJS&quot;</code></td>
<td>Specifies the module system.</td>
</tr>
<tr>
<td>moduleResolution</td>
<td><code>&quot;Node&quot;</code></td>
<td>Specifies the module resolution strategy.<br><code>&quot;NodeNext&quot;</code> supports the <code>exports</code> field and conditional resolution.<br><code>&quot;bundler&quot;</code> is a resolution strategy tailored to bundlers such as Vite and Webpack.</td>
</tr>
<tr>
<td>esModuleInterop</td>
<td><code>false</code></td>
<td>Enables ESM module compatibility.</td>
</tr>
<tr>
<td>isolatedModules</td>
<td><code>false</code></td>
<td>Compiles every file as a module, and raises an error if a file has no <code>import</code> or <code>export</code>.</td>
</tr>
<tr>
<td>moduleDetection</td>
<td>-</td>
<td>Specifies how modules are detected.<br><code>&quot;force&quot;</code> treats every file as a module to prevent global scope conflicts.</td>
</tr>
<tr>
<td>allowSyntheticDefaultImports</td>
<td><code>true</code></td>
<td>Allows default imports from modules that have no default export (<code>export default</code>).</td>
</tr>
<tr>
<td>allowImportingTsExtensions</td>
<td><code>false</code></td>
<td>Lets you use files with the <code>.ts</code> and <code>.tsx</code> extensions directly in <code>import</code> statements.</td>
</tr>
<tr>
<td>baseUrl</td>
<td>-</td>
<td>Specifies the base path used for module resolution.</td>
</tr>
<tr>
<td>paths</td>
<td>-</td>
<td>Specifies path aliases used for module resolution.</td>
</tr>
<tr>
<td>types</td>
<td>-</td>
<td>Specifies the list of <code>@types</code> packages the compiler references; packages not listed are ignored.</td>
</tr>
<tr>
<td>typeRoots</td>
<td><code>[&quot;./node_modules/@types&quot;]</code></td>
<td>Specifies the list of paths to type declarations (<code>.d.ts</code>) the compiler references; paths not listed are ignored.</td>
</tr>
<tr>
<td>allowJS</td>
<td><code>false</code></td>
<td>Allows compiling JS files.</td>
</tr>
<tr>
<td>checkJs</td>
<td><code>false</code></td>
<td>Whether to report errors in <code>.js</code> files.<br>Only takes effect when <code>allowJS</code> is <code>true</code>.</td>
</tr>
<tr>
<td>jsx</td>
<td><code>&quot;preserve&quot;</code></td>
<td>Specifies how JSX is compiled.<br><code>&quot;react-jsx&quot;</code> compiles with the new JSX Transform of React 17+.</td>
</tr>
<tr>
<td>declaration</td>
<td><code>true</code></td>
<td>Whether to generate declaration files (<code>*.d.ts</code>) that contain the type information of all TS (JS) files.</td>
</tr>
<tr>
<td>declarationMap</td>
<td><code>false</code></td>
<td>Whether to generate source map files (<code>.d.ts.map</code>) along with the <code>.d.ts</code> files.<br/>Useful for jumping to the source code while debugging.</td>
</tr>
<tr>
<td>sourceMap</td>
<td><code>false</code></td>
<td>Whether to generate source map files.<br/>Lets debugging tools and the like show the original TS file of a JS file.</td>
</tr>
<tr>
<td>noEmit</td>
<td><code>false</code></td>
<td>Doesn&#39;t generate output files (<code>.js</code>, <code>.d.ts</code>, and so on) after compilation.<br/>Use it when you only want to run type checks.</td>
</tr>
<tr>
<td>skipLibCheck</td>
<td><code>false</code></td>
<td>Skips type checking of <code>.d.ts</code> files.<br/>Ignores errors in third-party libraries and speeds up builds.</td>
</tr>
<tr>
<td>strict</td>
<td><code>false</code></td>
<td>Enables stricter type checking.<br/>Includes all strict options (<code>noImplicitAny</code>, <code>strictNullChecks</code>, and so on).</td>
</tr>
<tr>
<td>noImplicitAny</td>
<td><code>false</code></td>
<td>(strict) Enables checks for implicit <code>any</code> types.</td>
</tr>
<tr>
<td>noImplicitThis</td>
<td><code>false</code></td>
<td>(strict) Enables checks for implicit <code>this</code> types.</td>
</tr>
<tr>
<td>strictNullChecks</td>
<td><code>false</code></td>
<td>(strict) Enables strict <code>null</code> and <code>undefined</code> type checks.</td>
</tr>
<tr>
<td>strictFunctionTypes</td>
<td><code>false</code></td>
<td>(strict) Enables strict type checks for function parameters.</td>
</tr>
<tr>
<td>strictPropertyInitialization</td>
<td><code>false</code></td>
<td>(strict) Enables strict checks for class property initialization.</td>
</tr>
<tr>
<td>strictBindCallApply</td>
<td><code>false</code></td>
<td>(strict) Enables strict argument checks for the <code>bind</code>, <code>call</code>, and <code>apply</code> methods.</td>
</tr>
<tr>
<td>noUnusedLocals</td>
<td><code>false</code></td>
<td>Raises an error when there are unused local variables.</td>
</tr>
<tr>
<td>noUnusedParameters</td>
<td><code>false</code></td>
<td>Raises an error when there are unused function parameters.</td>
</tr>
<tr>
<td>noFallthroughCasesInSwitch</td>
<td><code>false</code></td>
<td>Forbids fall-through, where a <code>case</code> block of a <code>switch</code> statement falls into the next <code>case</code>, to prevent logic errors.</td>
</tr>
<tr>
<td>noUncheckedIndexedAccess</td>
<td><code>false</code></td>
<td>Includes the possibility of <code>undefined</code> in the type when you access an object by index.</td>
</tr>
<tr>
<td>noUncheckedSideEffectImports</td>
<td><code>false</code></td>
<td>Raises an error when an <code>import</code> that triggers a module&#39;s side effects isn&#39;t checked.<br/>Strengthens type safety (TypeScript 5.0+).</td>
</tr>
<tr>
<td>useDefineForClassFields</td>
<td><code>false</code></td>
<td>Follows the ECMAScript standard (<code>defineProperty</code>) behavior when declaring class fields.<br/>The default is <code>true</code> with <code>target: &quot;ES2022&quot;</code> or higher.</td>
</tr>
<tr>
<td>resolveJsonModule</td>
<td><code>false</code></td>
<td>Allows importing <code>.json</code> files as modules.</td>
</tr>
<tr>
<td>tsBuildInfoFile</td>
<td><code>.tsbuildinfo</code></td>
<td>Specifies the path of the <code>.tsbuildinfo</code> file for incremental compilation (recompiling only what changed since the previous compilation).</td>
</tr>
<tr>
<td>verbatimModuleSyntax</td>
<td><code>false</code></td>
<td>Interprets ES module (ECMAScript Modules) syntax more strictly and accurately</td>
</tr>
</tbody></table>
]]></description><link>https://www.heropy.dev/en/s/80</link><guid isPermaLink="false">/en/s/80</guid><category><![CDATA[TypeScript]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:36 GMT</pubDate></item><item><title><![CDATA[TypeScript Gets 10x Faster with a Native Port to Go]]></title><description><![CDATA[<p>On March 11, Microsoft announced that it would port the TypeScript compiler and toolset, which are currently written in TypeScript itself, to Go to greatly improve performance and the developer experience.<br>The current TypeScript compiler, <code>tsc</code>, runs on Node.js, so it needs a JavaScript runtime, and that has sometimes caused slowdowns in large projects.<br>With this native Go port, however, <code>tsc</code> will be able to run directly on the operating system without a separate runtime environment.<br>Although it is still in the early stages of development, Microsoft said this could cut <code>tsc</code> run times on large codebases by 10x or more.</p>
<p><img src="https://somwpkzlplaovldnfahk.supabase.co/storage/v1/object/public/heropy.dev_shorts/79/h6jL" alt="Comparison of TypeScript run times for each codebase" title="--496x300"></p>
<p>TypeScript, currently at version 5, plans to introduce deprecations and changes to some features for the native transition in the next version, 6, and to release the Go-based native compiler as TypeScript 7 once it reaches feature parity.<br>Microsoft also said its long-term goal is to let developers choose between the JavaScript-based version and the native version as needed.</p>
<p><a href="https://devblogs.microsoft.com/typescript/typescript-native-port/">A 10x Faster TypeScript</a></p>
]]></description><link>https://www.heropy.dev/en/s/79</link><guid isPermaLink="false">/en/s/79</guid><category><![CDATA[TypeScript]]></category><category><![CDATA[Go]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:36 GMT</pubDate></item><item><title><![CDATA[Create React App (CRA) Is Officially Deprecated]]></title><description><![CDATA[<p>As of February 14, 2025, creating new apps with Create React App (CRA) has been officially deprecated.<br>There had been earlier proposals to bring modern frameworks and build tools into CRA, but the CRA team said it would keep CRA as a minimal tool for starting a React app and recommended using separate modern tools when needed.<br>This time, however, they officially decided to deprecate it altogether.<br>So CRA is no longer a good fit for new projects, and we recommend building with other frameworks such as Next.js or React Router, or with modern build tools.</p>
<p>When it was released in 2016, CRA was a great way to start a React project easily while still meeting production requirements.<br>Today, however, there is much less need for CRA, because of its limits in building high-performance production apps, the lack of active maintainers, and the fact that other frameworks such as Next.js and React Router have already solved many of CRA&#39;s problems.</p>
<p>So CRA now moves into maintenance mode. A version that supports React 19 has been released, but new installs show a warning message that discourages you from using it.</p>
<p><img src="https://somwpkzlplaovldnfahk.supabase.co/storage/v1/object/public/heropy.dev_shorts/77/XBDF" alt="create-react-app is deprecated." title="--557x117"></p>
<p>From now on, it is recommended to build new apps with frameworks such as Next.js, React Router, or Expo, and to migrate existing apps to a framework or switch to a modern build tool such as Vite.</p>
<ul>
<li><a href="https://www.heropy.dev/p/6iFzkB">Starting a React Project with Vite</a></li>
<li><a href="https://www.heropy.dev/p/9tesDt">React Router Essentials</a></li>
<li><a href="https://www.heropy.dev/p/n7JHmI">Next.js 15 Essentials</a></li>
</ul>
]]></description><link>https://www.heropy.dev/en/s/77</link><guid isPermaLink="false">/en/s/77</guid><category><![CDATA[React]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:36 GMT</pubDate></item><item><title><![CDATA[Combining Default Key Bindings with Custom Keys in CodeMirror]]></title><description><![CDATA[<p>When you use <a href="https://codemirror.net/">CodeMirror</a>, you sometimes need to run extra custom behavior when a default key like <code>Backspace</code> or <code>Enter</code> is pressed, on top of its default action such as deleting text or inserting a line break.<br>However, CodeMirror gives priority to its default keymaps like <a href="https://codemirror.net/docs/ref/#commands.standardKeymap"><code>standardKeymap</code></a> and <a href="https://codemirror.net/docs/ref/#commands.defaultKeymap"><code>defaultKeymap</code></a>, so if you bind keys with a plain <code>keymap.of</code>, your custom behavior (function) cannot run.<br>In this case, you can use the <code>highest</code> method of the <code>Prec</code> (Precedence) module to make your custom keymap take priority over the default keymaps.</p>
<pre><code class="language-ts">import { EditorView } from &#39;codemirror&#39;
import { keymap } from &#39;@codemirror/view&#39;
import { Prec } from &#39;@codemirror/state&#39;

new EditorView({
  // ...
  extensions: [
    Prec.highest(
      keymap.of([
        {
          key: &#39;Backspace&#39;,
          run: () =&gt; {
            console.log(&#39;Backspace key!&#39;)
            return false // Moves on to the next handler, so the text can be deleted.
          }
        },
        {
          key: &#39;Enter&#39;,
          run: () =&gt; {
            console.log(&#39;Enter key!&#39;)
            return true // Does not move on to the next handler, so no line break is inserted.
          }
        }
      ])
    )
  ]
})
</code></pre>
<p>If the <code>run</code> function of a keymap returns <code>true</code>, the next handler does not run, so you can disable the default keymap.<br>On the other hand, if it returns <code>false</code>, the next handler runs, so you can combine your behavior with the default keymap.</p>
]]></description><link>https://www.heropy.dev/en/s/76</link><guid isPermaLink="false">/en/s/76</guid><category><![CDATA[Library]]></category><category><![CDATA[CodeMirror]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:36 GMT</pubDate></item><item><title><![CDATA[Optional Settings for the Zustand Persist Middleware (Using Storage)]]></title><description><![CDATA[<p>This post summarizes the optional settings you can use in Zustand&#39;s <a href="https://www.heropy.dev/p/n74Tgc#h3_%EC%8A%A4%ED%86%A0%EB%A6%AC%EC%A7%80_%EC%82%AC%EC%9A%A9_Persist">Persist middleware</a>.<br><code>name</code> is a required option.</p>
<p>All options are explained based on the following example.</p>
<pre><code class="language-ts">import { create } from &#39;zustand&#39;
import { combine, persist } from &#39;zustand/middleware&#39;

export const useCountStore = create(
  persist(
    combine(
      {
        count: 0,
        double: 0
      },
      set =&gt; ({
        increase: () =&gt; set(state =&gt; ({ count: state.count + 1 }))
      })
    ),
    {
      name: &#39;count&#39;
    }
  )
)
</code></pre>
<blockquote><p>For overall usage of Zustand, see <a href="https://www.heropy.dev/p/n74Tgc">Zustand Essentials</a>!</p>
</blockquote><h4>storage</h4>
<p>Instead of the default <a href="https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage">local storage (<code>localStorage</code>)</a>, you can use other storage such as session storage or IndexedDB.<br>If you want your own custom storage, return an object that matches the <code>StateStorage</code> interface through the <code>createJSONStorage</code> helper function.</p>
<pre><code class="language-ts">export interface StateStorage {
  getItem: (name: string) =&gt; string | null | Promise&lt;string | null&gt;;
  setItem: (name: string, value: string) =&gt; unknown | Promise&lt;unknown&gt;;
  removeItem: (name: string) =&gt; unknown | Promise&lt;unknown&gt;;
}
</code></pre>
<pre><code class="language-ts">// ...
export const useCountStore = create(
  persist(
    // combine(),
    {
      name: &#39;count&#39;,
      storage: createJSONStorage(() =&gt; sessionStorage) // Use session storage
    }
  )
)
</code></pre>
<h4>Partialize</h4>
<p>To save only the state you want instead of saving all state to storage, use the <code>partialize</code> option to return an object that contains only the state to save.<br>Because it&#39;s a factory function, you can transform the state when saving, but until rehydration, the current state (<code>currentState</code>) and the storage state (<code>persistedState</code>) may differ.<br>Hydration is explained in the next option.</p>
<pre><code class="language-ts">// ...
export const useCountStore = create(
  persist(
    // combine(),
    {
      name: &#39;count&#39;,
      partialize: currentState =&gt; ({ 
        count: currentState.count // Save only the count property to storage!
      })
    }
  )
)
</code></pre>
<h4>onRehydrateStorage</h4>
<p>The <code>onRehydrateStorage</code> option is a function that runs when the storage is hydrated.<br>You can write logic that needs to run right after hydration, and the <code>state</code> parameter of <code>onRehydrateStorage</code> includes the actions.</p>
<blockquote><p>In Zustand, <strong>hydration</strong> is the process of merging the state saved in storage with the current state.<br>You can also rehydrate manually at any time with the <code>useCountStore.persist.rehydrate()</code> method.<br>It&#39;s easiest to think of it as merging the storage state into the current state.</p>
</blockquote><pre><code class="language-ts">// ...
export const useCountStore = create(
  persist(
    // combine(),
    {
      name: &#39;count&#39;,
      onRehydrateStorage: state =&gt; {
        console.log(&#39;Merged with the storage state!&#39;, state)
      }
    }
  )
)
</code></pre>
<h4>skipHydration</h4>
<p>You can skip the initial hydration with the <code>skipHydration</code> option.<br>You can then rehydrate manually with the <code>useCountStore.persist.rehydrate()</code> method.</p>
<pre><code class="language-ts">// ...
export const useCountStore = create(
  persist(
    // combine(),
    {
      name: &#39;count&#39;,
      skipHydration: true
    }
  )
)
</code></pre>
<pre><code class="language-tsx">import { useCountStore } from &#39;./store/count&#39;

export default function RehydrateCountStore() {
  return (
    &lt;button onClick={() =&gt; useCountStore.persist.rehydrate()}&gt;
      Rehydrate!
    &lt;/button&gt;
  )
}
</code></pre>
<h4>version</h4>
<p>If you introduce changes that differ significantly from the data already saved in storage, you can specify a new version as a number so that storage data with a mismatched version isn&#39;t used.<br>If you need to make use of the old version&#39;s data instead of ignoring it, you can also use the <code>migrate</code> option described next.</p>
<pre><code class="language-ts">// ...
export const useCountStore = create(
  persist(
    // combine(),
    {
      name: &#39;count&#39;,
      version: 1 // Default: 0
    }
  )
)
</code></pre>
<h4>migrate</h4>
<p>The <code>migrate</code> function runs during hydration when the version of the current state differs from the version in storage.<br>The function must return state of a type that matches the latest version, and it&#39;s useful when you need to use the data in storage but its structure or names have changed.</p>
<pre><code class="language-ts">import { create } from &#39;zustand&#39;
import { combine, persist } from &#39;zustand/middleware&#39;

interface StateVersion0 {
  count: number
  double: number
}
interface StateVersion1 {
  amount: number
  multiplier: number
  max: number
}

export const useCountStore = create(
  persist(
    combine(
      {
        amount: 0,
        multiplier: 0
      },
      set =&gt; ({
        increase: () =&gt; set(state =&gt; ({ amount: state.amount + 1 }))
      })
    ),
    {
      name: &#39;count&#39;,
      version: 1,
      migrate: (persistedState, version) =&gt; {
        if (version === 0) {
          const oldState = persistedState as StateVersion0
          const newState: StateVersion1 = {
            amount: oldState.count,
            multiplier: oldState.double,
            max: 100
          }
          return newState
        }
        return persistedState
      }
    }
  )
)
</code></pre>
<h4>merge</h4>
<p>The <code>merge</code> option lets you specify how the storage state is merged with the current state during hydration.<br>By default, the storage state and the current state are shallow merged, but if you need a deep merge, you can use Lodash&#39;s <code>merge</code> function.<br>It runs after the <code>migrate</code> function (when both options are set), and it receives the value returned by <code>migrate</code> as its first parameter (<code>persistedState</code>).</p>
<pre><code class="language-bash">npm i lodash-es
npm i -D @types/lodash-es
</code></pre>
<pre><code class="language-ts">// ...
import { merge } from &#39;lodash-es&#39;

export const useCountStore = create(
  persist(
    // combine(),
    {
      name: &#39;count&#39;,
      merge: (persistedState, currentState) =&gt; {
        return merge(currentState, persistedState) // Deep merge the current state and the storage state
      }
    }
  )
)
</code></pre>
]]></description><link>https://www.heropy.dev/en/s/70</link><guid isPermaLink="false">/en/s/70</guid><category><![CDATA[React]]></category><category><![CDATA[Zustand]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:36 GMT</pubDate></item><item><title><![CDATA[Getting Started with the New Tailwind CSS v4 in a Next.js Project]]></title><description><![CDATA[<p>Tailwind CSS v4 was officially released on January 23.<br>Along with its major changes, it brings even better performance and usability.</p>
<ul>
<li>Builds up to 100x faster</li>
<li>Minimal installation and configuration code</li>
<li>Makes full use of modern CSS features (<code>@layer</code>, <code>@property</code>, <code>color-mix()</code>, and more)</li>
<li>Support for container queries, 3D transforms, and a new color system</li>
<li>More intuitive customization, configured directly in CSS without JS</li>
</ul>
<p>When you create a new project with the latest Next.js 15, Tailwind CSS v4 is applied by default.<br>If you want to use Tailwind CSS v4 in an existing Next project, set it up with the following steps.</p>
<p>First, install each package at its latest version.</p>
<pre><code class="language-bash">npm i -D tailwindcss@4 postcss @tailwindcss/postcss
</code></pre>
<p>Change the option name in the PostCSS configuration.</p>
<pre><code class="language-mjs">/** @type {import(&#39;postcss-load-config&#39;).Config} */
const config = {
  plugins: {
    // tailwindcss: {}
    &quot;@tailwindcss/postcss&quot;: {}
  }
}

export default config
</code></pre>
<p>Also change the style code that you import globally.</p>
<pre><code class="language-css">/* @tailwind base;
@tailwind components;
@tailwind utilities; */
@import &quot;tailwindcss&quot;;

/* Omitted.. */
</code></pre>
]]></description><link>https://www.heropy.dev/en/s/69</link><guid isPermaLink="false">/en/s/69</guid><category><![CDATA[CSS]]></category><category><![CDATA[Tailwindcss]]></category><category><![CDATA[Next]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:36 GMT</pubDate></item><item><title><![CDATA[Fixing the 'Account Action Required' Notification After Deleting a Google Account]]></title><description><![CDATA[<p>After I deleted a Google account I had used for work, my Galaxy smartphone kept showing an &#39;Account action required&#39; notification.<br>Even if I dismissed it, the notification came back after a while. The cause was that the account had not been removed from the phone itself.<br>So here is a simple way to remove the account from your phone.</p>
<p><img src="https://somwpkzlplaovldnfahk.supabase.co/storage/v1/object/public/heropy.dev_shorts/53/Echz" alt="Account action required notification" title="--800x449"></p>
<p>Open the phone&#39;s Settings, go to &#39;<strong>Accounts and backup</strong>&#39;, and select &#39;<strong>Manage accounts</strong>&#39;.</p>
<p><img src="https://somwpkzlplaovldnfahk.supabase.co/storage/v1/object/public/heropy.dev_shorts/53/5l3V" alt="Settings &gt; Accounts and backup &gt; Manage accounts" title="--800x961"></p>
<p>In the list of accounts (email addresses) on the phone, select the one you want to delete and remove it.</p>
<p><img src="https://somwpkzlplaovldnfahk.supabase.co/storage/v1/object/public/heropy.dev_shorts/53/C-WD" alt="Remove account" title="--800x961"></p>
]]></description><link>https://www.heropy.dev/en/s/53</link><guid isPermaLink="false">/en/s/53</guid><category><![CDATA[Mobile]]></category><category><![CDATA[Galaxy]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:36 GMT</pubDate></item><item><title><![CDATA[A Summary of Data Types for Supabase Table Columns]]></title><description><![CDATA[<p>When you create a table in Supabase (PostgreSQL), choosing the data type of each column is important for using your data efficiently and optimizing search and processing performance.<br>It also affects more than just how data is stored, such as how you extend and maintain the database later, so it calls for careful design.</p>
<p><img src="https://somwpkzlplaovldnfahk.supabase.co/storage/v1/object/public/heropy.dev_shorts/51/hjyd" alt="Supabase Table Data Type" title="--507x438"></p>
<p>If you&#39;re new to PostgreSQL data types or aren&#39;t familiar with them, it can be hard to know which type to choose.<br>So, to help you choose a data type, I&#39;ve organized them into a table with descriptions as follows.<br>Use the table to design a database structure that fits your project!</p>
<table>
<thead>
<tr>
<th>Supabase</th>
<th>Prisma</th>
<th>TypeScript</th>
<th>Description</th>
</tr>
</thead>
<tbody><tr>
<td><code>int2</code></td>
<td><code>Int</code></td>
<td><code>number</code></td>
<td>Used for integer values in a small range (<code>-32,768</code> to <code>+32,767</code>), such as grades, ages, and ratings.<br/>It can save a bit more storage space when you handle large amounts of data.</td>
</tr>
<tr>
<td><code>int4</code></td>
<td><code>Int</code></td>
<td><code>number</code></td>
<td>Integer values in the most common range (<code>-2,147,483,648</code> to <code>+2,147,483,647</code>).</td>
</tr>
<tr>
<td><code>int8</code></td>
<td><code>BigInt</code></td>
<td><code>bigint</code></td>
<td>Integer values in a very large range (<code>-9,223,372,036,854,775,808</code> to <code>+9,223,372,036,854,775,807</code>).<br/>Used when values need a very large range, such as IDs for large datasets, view counts, and large amounts of money.</td>
</tr>
<tr>
<td><code>float4</code></td>
<td><code>Float</code></td>
<td><code>number</code></td>
<td>A floating-point value with precision of up to 6 digits after the decimal point.<br/>Used when memory efficiency matters or when you don&#39;t need high precision, such as for temperatures and coordinates.</td>
</tr>
<tr>
<td><code>float8</code></td>
<td><code>Float</code></td>
<td><code>number</code></td>
<td>A floating-point value with precision of up to 15 digits after the decimal point.<br/>Used when you need more precise calculations, such as scientific computing and aviation data.</td>
</tr>
<tr>
<td><code>numeric</code></td>
<td><code>Decimal</code></td>
<td><code>Decimal</code></td>
<td>Used when you need decimal calculations that demand perfect accuracy with no room for error, such as financial transactions and accounting.<br/>Processing is relatively slow.</td>
</tr>
<tr>
<td><code>json</code></td>
<td><code>Json</code></td>
<td><code>Prisma.JsonValue</code></td>
<td>Stores structured JSON data as a string.<br/>It has to be parsed every time the data is processed, so unless you&#39;re only storing it, we recommend using <code>jsonb</code>.</td>
</tr>
<tr>
<td><code>jsonb</code></td>
<td><code>Json</code></td>
<td><code>Prisma.JsonValue</code></td>
<td>Stores JSON data in binary form.<br/>It&#39;s fast to process and supports indexing, so it&#39;s useful when you often need to search or modify the data.</td>
</tr>
<tr>
<td><code>text</code></td>
<td><code>String</code></td>
<td><code>string</code></td>
<td>A string with no length limit, such as long text or post content.</td>
</tr>
<tr>
<td><code>varchar</code></td>
<td><code>String</code></td>
<td><code>string</code></td>
<td>A string with a limited length, such as a username or email.<br/>Checking the length limit can add a little overhead, so in most cases we recommend using <code>text</code>.</td>
</tr>
<tr>
<td><code>uuid</code></td>
<td><code>String</code></td>
<td><code>string</code></td>
<td>Stores a universally unique identifier.<br/>Used when you need a unique ID, and it consists of 32 hexadecimal digits.</td>
</tr>
<tr>
<td><code>date</code></td>
<td><code>DateTime</code></td>
<td><code>Date</code></td>
<td>Stores a date without time information, and is used for things like birthdays and anniversaries.<br/>We recommend using <code>timestamptz</code>.<br/>Example) <code>2025-12-16</code> =&gt; <code>2025-12-16T00:00:00.000Z</code></td>
</tr>
<tr>
<td><code>time</code></td>
<td><code>DateTime</code></td>
<td><code>Date</code></td>
<td>Stores only the time without date information, and is used for things like business hours and daily schedules.<br/>We recommend using <code>timestamptz</code>.<br/>Example) <code>08:10:28</code> =&gt; <code>1970-01-01T08:10:28.000Z</code></td>
</tr>
<tr>
<td><code>timetz</code></td>
<td><code>DateTime</code></td>
<td><code>Date</code></td>
<td>Stores the time together with time zone information.<br/>We recommend using <code>timestamptz</code>.<br/>Example) <code>08:10:28+00</code> =&gt; <code>1970-01-01T08:10:28.000Z</code></td>
</tr>
<tr>
<td><code>timestamp</code></td>
<td><code>DateTime</code></td>
<td><code>Date</code></td>
<td>Stores the date and time together, and is used for things like when an event occurred or when data was created/updated.<br/>We recommend using <code>timestamptz</code>.<br/>Example) <code>2025-01-15 08:10:28.000</code> =&gt; <code>2025-01-15T08:10:28.000Z</code></td>
</tr>
<tr>
<td><code>timestamptz</code></td>
<td><code>DateTime</code></td>
<td><code>Date</code></td>
<td>Stores the date, time, and time zone information all together.<br/>Used when a global service needs to take time zones into account, and it&#39;s the most recommended option.<br/>Example) <code>2025-01-15 08:10:28.000+00</code> =&gt; <code>2025-01-15T08:10:28.000Z</code></td>
</tr>
<tr>
<td><code>bool</code></td>
<td><code>Boolean</code></td>
<td><code>boolean</code></td>
<td>Stores a true/false Boolean value.</td>
</tr>
</tbody></table>
]]></description><link>https://www.heropy.dev/en/s/51</link><guid isPermaLink="false">/en/s/51</guid><category><![CDATA[DB]]></category><category><![CDATA[PostgreSQL]]></category><category><![CDATA[Supabase]]></category><category><![CDATA[Prisma]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:36 GMT</pubDate></item><item><title><![CDATA[When Pasting Doesn't Work in the Chrome DevTools Console]]></title><description><![CDATA[<p>When you try to paste copied text into the Chrome DevTools console, a warning message may appear and the paste may not go through.<br>In that case, type <code>allow pasting</code> (or <code>붙여넣기 허용</code> if Chrome is set to Korean) in the console, and pasting will work normally.</p>
<p><img src="https://somwpkzlplaovldnfahk.supabase.co/storage/v1/object/public/heropy.dev_shorts/50/A-Gq" alt="Typing allow pasting in Korean" title="--599x235"></p>
]]></description><link>https://www.heropy.dev/en/s/50</link><guid isPermaLink="false">/en/s/50</guid><category><![CDATA[DevTools]]></category><category><![CDATA[Chrome]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:36 GMT</pubDate></item><item><title><![CDATA[Offset and Cursor Pagination]]></title><description><![CDATA[<p>Offset-based pagination, which uses an offset (start) and a limit, is the most common approach, but there is also cursor-based pagination.<br>When you fetch data page by page with offsets, you can get duplicated or missing items if data is added or deleted quickly in real time.<br>Cursor-based pagination, on the other hand, uses the position of the last item as a cursor and fetches the data that comes after it, so it is especially useful when data is added or deleted often.</p>
<pre><code class="language-sql">-- Offset
SELECT *
FROM table_name
ORDER BY created_at DESC
LIMIT 10
OFFSET 10

-- Cursor
SELECT *
FROM table_name
WHERE created_at &lt; :cursor_created_at
ORDER BY created_at DESC
LIMIT 10
</code></pre>
]]></description><link>https://www.heropy.dev/en/s/48</link><guid isPermaLink="false">/en/s/48</guid><category><![CDATA[DB]]></category><category><![CDATA[SQL]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:36 GMT</pubDate></item><item><title><![CDATA[Syncing One Skill Across Multiple AI Agents with @heropy/symlink]]></title><description><![CDATA[<p>An AI agent skill is a single folder that contains a <code>SKILL.md</code> file.<br>It is published as an <a href="https://agentskills.io/">open standard</a>, so many tools use the same format, but the standard only covers the folder structure and the <code>SKILL.md</code> format.<br>Where to look for skills is up to each tool.</p>
<table>
<thead>
<tr>
<th>Tool</th>
<th>Project skill path</th>
</tr>
</thead>
<tbody><tr>
<td>Claude Code</td>
<td><code>.claude/skills/</code></td>
</tr>
<tr>
<td>Codex</td>
<td><code>.agents/skills/</code></td>
</tr>
<tr>
<td>Gemini CLI</td>
<td><code>.agents/skills/</code>, <code>.gemini/skills/</code></td>
</tr>
<tr>
<td>Cursor</td>
<td><code>.agents/skills/</code>, <code>.cursor/skills/</code>, <code>.claude/skills/</code></td>
</tr>
</tbody></table>
<p><code>.agents/skills/</code> is a shared path that doesn&#39;t belong to any specific tool, but Claude Code only checks <code>.claude/skills/</code>.<br>If you use Claude Code together with other AI agents like Codex or Cursor in one project, the same skill has to exist in both paths.</p>
<p>If you simply copy the folder, you end up with two or more copies of the same skill.<br>Once you edit one of them, the copies drift apart, and it becomes hard to tell or manage which one is the latest.<br>This is where a symbolic link helps: you keep the original in one place and have the other path point to it.</p>
<h4>What is a symbolic link</h4>
<p>A symbolic link is a special file that stores the path of another file or folder.<br>When you open the link, it follows the stored path and opens the original, so programs treat the link and the original as the same folder without telling them apart.<br>On macOS and Linux, you create one with the <code>ln -s</code> command.</p>
<pre><code class="language-bash">ln -s ../../.claude/skills/my-skill .agents/skills/my-skill
</code></pre>
<p>Now, if you edit <code>.agents/skills/my-skill/SKILL.md</code>, <code>.claude/skills/my-skill/SKILL.md</code> changes too.<br>Both paths point to the same file, so an edit on either side shows up on the other side right away.<br>Deleting the link leaves the original untouched, but deleting the original leaves the link as a broken link with nothing to point to.</p>
<p>However, linking skill folders by hand comes with a lot to check.</p>
<ul>
<li>A relative path is resolved from where the link is created, not from where you run the command, so if you leave out <code>../../</code> in the command above, you get a broken link.</li>
<li>You have to run one command per skill, and repeat it every time you add a skill.</li>
<li>If some skills have their original in <code>.claude/skills</code> and others in <code>.agents/skills</code>, you also have to check the link direction for each skill.</li>
<li>On Windows, you use the <code>mklink</code> command, and creating a symbolic link requires Developer Mode or administrator privileges.</li>
</ul>
<h4>Creating links the easy way</h4>
<p><a href="https://www.npmjs.com/package/@heropy/symlink">@heropy/symlink</a> is a CLI tool that compares the entries in several folders and creates symbolic links on the side where they are missing.<br>You pass the folders to link as arguments, and you can run it with <code>npx</code> without installing anything.</p>
<blockquote><p>It works on Node.js 20.19 or later.</p>
</blockquote><pre><code class="language-bash">npx @heropy/symlink .claude/skills .agents/skills
## link   .agents/skills/commit-push -&gt; ../../.claude/skills/commit-push
## link   .agents/skills/writing-style -&gt; ../../.claude/skills/writing-style
## link   .claude/skills/react-router -&gt; ../../.agents/skills/react-router
##
## 3 linked
</code></pre>
<p><code>commit-push</code> and <code>writing-style</code> have their originals in <code>.claude/skills</code>, so links were created in <code>.agents/skills</code>, and <code>react-router</code> is the other way around.<br>No matter what order you write the arguments in, the side that holds the actual folder becomes the original, and the relative path of each link is calculated from the link&#39;s location.<br>So you don&#39;t have to worry about which path you added a skill to or how to write the path.</p>
<p>When you add a new skill, run the same command again.<br>Entries that are already linked are reported as <code>keep</code> and left as they are, and only the new skill gets linked.</p>
<pre><code class="language-bash">npx @heropy/symlink .claude/skills .agents/skills
## keep   .agents/skills/heropy-commit-push
## keep   .agents/skills/heropy-writing-style
## link   .agents/skills/lighthouse -&gt; ../../.claude/skills/lighthouse
## keep   .claude/skills/react-router
##
## 1 linked, 3 already fine
</code></pre>
<p>Running it many times gives the same result, so it is safe to add to a <code>postinstall</code> script.<br>It never deletes an existing file or folder to make room, and for entries you need to decide on yourself, such as when an original with the same name exists on both sides, it skips them and prints the reason.<br>On Windows, it creates directory junctions, which need no special privileges, so you can use the same command on any operating system.</p>
<p>AI skills were just the reason I built this tool. Any folder that each tool expects at its own fixed path, such as shared settings, prompt collections, or static assets, can be linked the same way.<br>For options like <code>--dry-run</code>, <code>--list</code>, and <code>--unlink</code>, notes on Windows, the Node.js API, and more, see the <a href="https://github.com/ParkYoungWoong/heropy.symlink">GitHub repository</a>.</p>
]]></description><link>https://www.heropy.dev/en/s/102</link><guid isPermaLink="false">/en/s/102</guid><category><![CDATA[Agent Skills]]></category><category><![CDATA[Claude]]></category><category><![CDATA[Codex]]></category><category><![CDATA[CLI]]></category><category><![CDATA[Node.js]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:36 GMT</pubDate></item><item><title><![CDATA[JSON Server Essentials]]></title><description><![CDATA[JSON Server is a tool that lets you build a mock REST API server and DB with a JSON file. With it, you can develop or test prototypes even when the backend API server or DB is not ready yet.]]></description><link>https://www.heropy.dev/en/p/zZdlXx</link><guid isPermaLink="false">/en/p/zZdlXx</guid><category><![CDATA[JSON]]></category><category><![CDATA[Server]]></category><category><![CDATA[DB]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:36 GMT</pubDate></item><item><title><![CDATA[TypeScript Utility Types in Depth]]></title><description><![CDATA[TypeScript provides a variety of built-in utility types that you can use to transform and manipulate types. With them, you can make your code more reusable and write code that is more concise and easier to read.]]></description><link>https://www.heropy.dev/en/p/zZIUWd</link><guid isPermaLink="false">/en/p/zZIUWd</guid><category><![CDATA[TypeScript]]></category><category><![CDATA[Utility Types]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:36 GMT</pubDate></item><item><title><![CDATA[Vue Composition API Core Patterns with TypeScript]]></title><description><![CDATA[If you've finished learning the basic syntax of Vue 3, quickly explore the core patterns that use the Composition API and TypeScript!]]></description><link>https://www.heropy.dev/en/p/zDWwNL</link><guid isPermaLink="false">/en/p/zDWwNL</guid><category><![CDATA[Vue]]></category><category><![CDATA[Composition API]]></category><category><![CDATA[TypeScript]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:36 GMT</pubDate></item><item><title><![CDATA[Git/GitHub Installation and Usage Guide]]></title><description><![CDATA[Learn the concept of a version control system (VCS), basic Git commands, and how to connect to a GitHub remote repository. This post covers the whole workflow, from installation to init, add, commit, push, pull, and clone.]]></description><link>https://www.heropy.dev/en/p/z9Z49c</link><guid isPermaLink="false">/en/p/z9Z49c</guid><category><![CDATA[Git]]></category><category><![CDATA[GitHub]]></category><category><![CDATA[VCS]]></category><category><![CDATA[버전 관리]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:35 GMT</pubDate></item><item><title><![CDATA[JS Intersection Observer: Observing Element Visibility]]></title><description><![CDATA[Intersection Observer watches the intersection between the browser viewport and a target element, and lets you tell whether the element is inside the viewport or not, or more simply, whether it's currently visible on the user's screen.]]></description><link>https://www.heropy.dev/en/p/ydKoQO</link><guid isPermaLink="false">/en/p/ydKoQO</guid><category><![CDATA[JS]]></category><category><![CDATA[Intersection Observer]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:35 GMT</pubDate></item><item><title><![CDATA[CSS ::before and ::after Selectors]]></title><description><![CDATA[The CSS ::before and ::after pseudo-element selectors are a powerful tool that lets you add content inside a specific HTML element with CSS. With them, you can add or change visual elements without changing the HTML structure, so you can build more dynamic and polished web pages.]]></description><link>https://www.heropy.dev/en/p/yUnC6g</link><guid isPermaLink="false">/en/p/yUnC6g</guid><category><![CDATA[CSS]]></category><category><![CDATA[Before]]></category><category><![CDATA[After]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:35 GMT</pubDate></item><item><title><![CDATA[First Steps in HTML and CSS]]></title><description><![CDATA[Learn the basics of HTML and CSS to start web development. This is an ideal guide for complete beginners.]]></description><link>https://www.heropy.dev/en/p/xCoQJR</link><guid isPermaLink="false">/en/p/xCoQJR</guid><category><![CDATA[HTML]]></category><category><![CDATA[CSS]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:35 GMT</pubDate></item><item><title><![CDATA[Understanding Bundlers and Build Tools]]></title><description><![CDATA[Bundlers such as Webpack, Parcel, and Rollup are essential tools in modern web development. This post covers the basic concepts of bundlers, how they work, and simple examples, and then also looks at the concept of build tools with examples.]]></description><link>https://www.heropy.dev/en/p/x8iedW</link><guid isPermaLink="false">/en/p/x8iedW</guid><category><![CDATA[Bundler]]></category><category><![CDATA[Webpack]]></category><category><![CDATA[SWC]]></category><category><![CDATA[Parcel]]></category><category><![CDATA[Vite]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:35 GMT</pubDate></item><item><title><![CDATA[Using GA4 Query Explorer and the Google Analytics Data API]]></title><description><![CDATA[Learn how to get your website's traffic information from Google Analytics with GA4 Query Explorer and the Google Analytics Data API. (GA4 Query Explorer, Google Analytics Data API)]]></description><link>https://www.heropy.dev/en/p/wc7QvJ</link><guid isPermaLink="false">/en/p/wc7QvJ</guid><category><![CDATA[GA4 Query Explorer]]></category><category><![CDATA[Google Analytics Data API]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:35 GMT</pubDate></item><item><title><![CDATA[React Hooks Essentials]]></title><description><![CDATA[Learn how to use every built-in hook that React provides and how to write your own custom hooks.]]></description><link>https://www.heropy.dev/en/p/revOrg</link><guid isPermaLink="false">/en/p/revOrg</guid><category><![CDATA[React]]></category><category><![CDATA[Hooks]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:35 GMT</pubDate></item><item><title><![CDATA[Stopping a MongoDB Instance That Is Already Running]]></title><description><![CDATA[When MongoDB shuts down abnormally while running, you may need to find and stop the process on its old port before you can start MongoDB again. Let's see how.]]></description><link>https://www.heropy.dev/en/p/qzeuNi</link><guid isPermaLink="false">/en/p/qzeuNi</guid><category><![CDATA[MongoDB]]></category><category><![CDATA[DB]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:35 GMT</pubDate></item><item><title><![CDATA[Essential JS + TS Core Syntax]]></title><description><![CDATA[A summary, with diagrams and examples, of the core JavaScript and TypeScript syntax you use every day in web development. You need it no matter which framework you use, whether React, Vue, or Svelte.]]></description><link>https://www.heropy.dev/en/p/qYpNij</link><guid isPermaLink="false">/en/p/qYpNij</guid><category><![CDATA[JS]]></category><category><![CDATA[TypeScript]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:35 GMT</pubDate></item><item><title><![CDATA[Optimizing Next.js Bundle Size]]></title><description><![CDATA[Learn how to optimize the bundle size of a Next.js application. This post explains how to analyze your bundle size and reduce it effectively with techniques such as code splitting and tree shaking.]]></description><link>https://www.heropy.dev/en/p/pd8CoS</link><guid isPermaLink="false">/en/p/pd8CoS</guid><category><![CDATA[React]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[Bundle]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:35 GMT</pubDate></item><item><title><![CDATA[Next.js 16 Essentials]]></title><description><![CDATA[Next.js is a React framework developed by Vercel that provides a variety of optimization features, such as server-side rendering (SSR), client-side rendering (CSR), and API routing. With Next.js, you can extend React's core features to build web applications faster and more reliably.]]></description><link>https://www.heropy.dev/en/p/n7JHmI</link><guid isPermaLink="false">/en/p/n7JHmI</guid><category><![CDATA[React]]></category><category><![CDATA[Next.js]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:35 GMT</pubDate></item><item><title><![CDATA[Zustand Essentials]]></title><description><![CDATA[Zustand is a small, fast, and scalable state management (store) library for React projects.]]></description><link>https://www.heropy.dev/en/p/n74Tgc</link><guid isPermaLink="false">/en/p/n74Tgc</guid><category><![CDATA[React]]></category><category><![CDATA[Zustand]]></category><category><![CDATA[Store]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:34 GMT</pubDate></item><item><title><![CDATA[Zod Essentials - Runtime Type Validation with TypeScript]]></title><description><![CDATA[TypeScript gives you strong type checking at compile time, but it can't guarantee type safety at runtime. Zod is a library that validates data at runtime, and using it together with TypeScript's compile-time type checking gives you stronger type safety.]]></description><link>https://www.heropy.dev/en/p/mJAAl7</link><guid isPermaLink="false">/en/p/mJAAl7</guid><category><![CDATA[Zod]]></category><category><![CDATA[TypeScript]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:34 GMT</pubDate></item><item><title><![CDATA[Orca Essentials]]></title><description><![CDATA[Orca is an open-source desktop app that runs multiple CLI agents, such as Claude Code and Codex, side by side in a separate folder for each task and lets you manage them on screen. With real screenshots, this post covers what is set up automatically after installation and what you need to prepare yourself, the flow of assigning work and reviewing and applying the results, and orchestration, which lets agents work together.]]></description><link>https://www.heropy.dev/en/p/im8VPa</link><guid isPermaLink="false">/en/p/im8VPa</guid><category><![CDATA[AI]]></category><category><![CDATA[Orca]]></category><category><![CDATA[Agent]]></category><category><![CDATA[Claude Code]]></category><category><![CDATA[Codex]]></category><category><![CDATA[Git]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:34 GMT</pubDate></item><item><title><![CDATA[Installing and Using Yarn]]></title><description><![CDATA[Let's try Yarn, the JavaScript package manager created by Meta (formerly Facebook).]]></description><link>https://www.heropy.dev/en/p/ijqX9h</link><guid isPermaLink="false">/en/p/ijqX9h</guid><category><![CDATA[Yarn]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:34 GMT</pubDate></item><item><title><![CDATA[Claude Cowork Essentials]]></title><description><![CDATA[Claude Cowork is an agentic work tool in Claude Desktop that moves between files, folders, and apps to carry out the work you assign. This post covers its core features, from an introduction and installation to basic usage, connectors, computer use, and work automation pipelines.]]></description><link>https://www.heropy.dev/en/p/gECL4R</link><guid isPermaLink="false">/en/p/gECL4R</guid><category><![CDATA[Claude]]></category><category><![CDATA[Claude Cowork]]></category><category><![CDATA[Agent]]></category><category><![CDATA[MCP]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:34 GMT</pubDate></item><item><title><![CDATA[The Complete Guide to CSS Grid]]></title><description><![CDATA[CSS Grid is a CSS technology that provides a two-dimensional layout system, letting you arrange the elements of a web page in a grid made of rows and columns. It makes even complex layouts easy to build, so it is well suited to precise design work.]]></description><link>https://www.heropy.dev/en/p/c6ROLZ</link><guid isPermaLink="false">/en/p/c6ROLZ</guid><category><![CDATA[CSS]]></category><category><![CDATA[Grid]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:34 GMT</pubDate></item><item><title><![CDATA[Pinia Essentials]]></title><description><![CDATA[Pinia is a simple and flexible state management library optimized for the Vue Composition API and TypeScript. Along with a store's state, getters, and actions, we also look at how to use handy instance members such as $patch and $subscribe.]]></description><link>https://www.heropy.dev/en/p/bdPf3j</link><guid isPermaLink="false">/en/p/bdPf3j</guid><category><![CDATA[Vue]]></category><category><![CDATA[Pinia]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:34 GMT</pubDate></item><item><title><![CDATA[Node.js (NPM) Installation and NVM Version Management Guide]]></title><description><![CDATA[Learn how to install Node.js and NPM. We'll look in detail at installing them with the official installer or NVM, and at managing versions.]]></description><link>https://www.heropy.dev/en/p/bVoDlS</link><guid isPermaLink="false">/en/p/bVoDlS</guid><category><![CDATA[Node.js]]></category><category><![CDATA[NPM]]></category><category><![CDATA[NVM]]></category><category><![CDATA[NVM-Windows]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:34 GMT</pubDate></item><item><title><![CDATA[TypeScript Enum Types in Depth]]></title><description><![CDATA[A detailed look at enums in TypeScript, which you can use as both a type and data. This post covers the basic number and string patterns of enums, along with practical examples.]]></description><link>https://www.heropy.dev/en/p/arpi5F</link><guid isPermaLink="false">/en/p/arpi5F</guid><category><![CDATA[TypeScript]]></category><category><![CDATA[Enum]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:34 GMT</pubDate></item><item><title><![CDATA[Starting a Vue Project with Vite]]></title><description><![CDATA[This post walks through how to start a Vue project with the Vite.js build tool, and explains the configuration for JavaScript and TypeScript projects separately.]]></description><link>https://www.heropy.dev/en/p/aBLqC5</link><guid isPermaLink="false">/en/p/aBLqC5</guid><category><![CDATA[Vue]]></category><category><![CDATA[Vite]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:34 GMT</pubDate></item><item><title><![CDATA[JS Async Core Patterns]]></title><description><![CDATA[Learn the difference between code that runs synchronously and code that runs asynchronously, and explore several core patterns for writing asynchronous code.]]></description><link>https://www.heropy.dev/en/p/Zr4RfI</link><guid isPermaLink="false">/en/p/Zr4RfI</guid><category><![CDATA[JS]]></category><category><![CDATA[Async/Await]]></category><category><![CDATA[Promise]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:34 GMT</pubDate></item><item><title><![CDATA[The Complete Guide to SCSS/Sass]]></title><description><![CDATA[Understand SCSS/Sass, a CSS preprocessor, and explore SCSS syntax in detail, from compiling to CSS to the module system and built-in modules.]]></description><link>https://www.heropy.dev/en/p/Y7OrPe</link><guid isPermaLink="false">/en/p/Y7OrPe</guid><category><![CDATA[SCSS]]></category><category><![CDATA[Sass]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:33 GMT</pubDate></item><item><title><![CDATA[Setting Up a New MacBook: Notes for Myself]]></title><description><![CDATA[I put together what you need when you buy a new MacBook and set it up for the first time. I share how to configure system settings and how to install and set up Homebrew, Git, NVM, a terminal theme, essential apps, and more.]]></description><link>https://www.heropy.dev/en/p/XQ4pkx</link><guid isPermaLink="false">/en/p/XQ4pkx</guid><category><![CDATA[macOS]]></category><category><![CDATA[macbook]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:33 GMT</pubDate></item><item><title><![CDATA[TypeScript at a Glance]]></title><description><![CDATA[TypeScript is an open-source language under the Apache License, developed and maintained by Microsoft. It applies a strong type system to JavaScript, so you can catch most errors in the compile environment while you type your code.]]></description><link>https://www.heropy.dev/en/p/WhqSC8</link><guid isPermaLink="false">/en/p/WhqSC8</guid><category><![CDATA[TypeScript]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:33 GMT</pubDate></item><item><title><![CDATA[Claude Code Built-in Slash Commands Essentials]]></title><description><![CDATA[A guide to Claude Code's built-in slash commands, ordered by how often you use them. For commands you operate on screen, such as session management, context checks, rewinding, repeated runs, and remote connections, it shows how to use them and how they differ with real screenshots and diagrams.]]></description><link>https://www.heropy.dev/en/p/VTowf9</link><guid isPermaLink="false">/en/p/VTowf9</guid><category><![CDATA[Claude Code]]></category><category><![CDATA[AI]]></category><category><![CDATA[Slash Commands]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:33 GMT</pubDate></item><item><title><![CDATA[Understanding JS Blob]]></title><description><![CDATA[A Blob (Binary Large Object) can be used to handle multimedia data such as images, sounds, and videos. In this post, we look at how to create, read, and write Blobs.]]></description><link>https://www.heropy.dev/en/p/QlwiuS</link><guid isPermaLink="false">/en/p/QlwiuS</guid><category><![CDATA[JS]]></category><category><![CDATA[Blob]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:33 GMT</pubDate></item><item><title><![CDATA[React Core Patterns with TypeScript]]></title><description><![CDATA[Let's look at various usage patterns of React's basic syntax, along with how to use TypeScript with them.]]></description><link>https://www.heropy.dev/en/p/QduRma</link><guid isPermaLink="false">/en/p/QduRma</guid><category><![CDATA[React]]></category><category><![CDATA[TypeScript]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:33 GMT</pubDate></item><item><title><![CDATA[(Draft) SvelteKit]]></title><description><![CDATA[SvelteKit is a Svelte framework that provides fast builds based on server-side rendering (SSR) and a simple routing system, along with several features that improve performance, such as SEO optimization.]]></description><link>https://www.heropy.dev/en/p/QWrwz3</link><guid isPermaLink="false">/en/p/QWrwz3</guid><category><![CDATA[Svelte]]></category><category><![CDATA[SvelteKit]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:32 GMT</pubDate></item><item><title><![CDATA[Fetch vs Axios - A Guide to HTTP Data Communication]]></title><description><![CDATA[Data communication between the server and the client is one of the core concepts of web development. Learn how to use the fetch function and the axios library for data communication in JavaScript.]]></description><link>https://www.heropy.dev/en/p/QOWqjV</link><guid isPermaLink="false">/en/p/QOWqjV</guid><category><![CDATA[JS]]></category><category><![CDATA[Fetch]]></category><category><![CDATA[Axios]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:32 GMT</pubDate></item><item><title><![CDATA[Essential Git Commands]]></title><description><![CDATA[A quick summary of the commands you use most often in Git, the version control system (VCS).]]></description><link>https://www.heropy.dev/en/p/PcUkdT</link><guid isPermaLink="false">/en/p/PcUkdT</guid><category><![CDATA[Git]]></category><category><![CDATA[GitHub]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:32 GMT</pubDate></item><item><title><![CDATA[React Core Patterns]]></title><description><![CDATA[Explore various usage patterns of React's basic syntax.]]></description><link>https://www.heropy.dev/en/p/OidQSe</link><guid isPermaLink="false">/en/p/OidQSe</guid><category><![CDATA[React]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:32 GMT</pubDate></item><item><title><![CDATA[Key Optimization Strategies for a Claude Code Token Diet]]></title><description><![CDATA[This post summarizes token management strategies to avoid the usage limit message in Claude Code and keep response quality high. Put model selection, effort level tuning, context management, prompt caching, and more to work right away.]]></description><link>https://www.heropy.dev/en/p/ODra43</link><guid isPermaLink="false">/en/p/ODra43</guid><category><![CDATA[Claude Code]]></category><category><![CDATA[AI]]></category><category><![CDATA[Token]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:32 GMT</pubDate></item><item><title><![CDATA[The Complete Guide to CSS Multi-Column]]></title><description><![CDATA[CSS multi-column is a layout feature that splits an element's content (such as text) into several columns, like a newspaper or magazine, so you can see more content at a glance and read it more easily.]]></description><link>https://www.heropy.dev/en/p/NSH7aj</link><guid isPermaLink="false">/en/p/NSH7aj</guid><category><![CDATA[CSS]]></category><category><![CDATA[Multi Column]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:32 GMT</pubDate></item><item><title><![CDATA[JS Function Core Patterns]]></title><description><![CDATA[Explore a variety of function patterns and concepts in JavaScript, from the basics of using functions to related terms and advanced techniques.]]></description><link>https://www.heropy.dev/en/p/N6phSt</link><guid isPermaLink="false">/en/p/N6phSt</guid><category><![CDATA[JS]]></category><category><![CDATA[Functions]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:32 GMT</pubDate></item><item><title><![CDATA[Auth.js (NextAuth.js) Essentials]]></title><description><![CDATA[Auth.js (NextAuth.js) is a library for user authentication and session management in Next.js projects. It supports many authentication providers such as Google and GitHub, and makes it easy to handle authentication and sessions on both the server and client sides of Next.js.]]></description><link>https://www.heropy.dev/en/p/MI1Khc</link><guid isPermaLink="false">/en/p/MI1Khc</guid><category><![CDATA[React]]></category><category><![CDATA[Next.js]]></category><category><![CDATA[NextAuth.js]]></category><category><![CDATA[Auth.js]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:32 GMT</pubDate></item><item><title><![CDATA[Key HTML Elements and Attributes at a Glance]]></title><description><![CDATA[Through a short overview and description of the HTML elements and attributes used in web development projects, learn what you need to design and build web pages. This helps you follow web standards while building an effective, semantic markup structure.]]></description><link>https://www.heropy.dev/en/p/LWIk13</link><guid isPermaLink="false">/en/p/LWIk13</guid><category><![CDATA[HTML]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:32 GMT</pubDate></item><item><title><![CDATA[React Compiler Essentials]]></title><description><![CDATA[React Compiler is a tool that automatically optimizes React applications at build time, so you can get optimal performance without manual memoization.]]></description><link>https://www.heropy.dev/en/p/IURkhb</link><guid isPermaLink="false">/en/p/IURkhb</guid><category><![CDATA[React]]></category><category><![CDATA[Compiler]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:31 GMT</pubDate></item><item><title><![CDATA[The Complete Guide to CSS Flex]]></title><description><![CDATA[CSS Flex is a technique for designing efficient layouts that lets you flexibly manage how space is distributed and how items are aligned within a container. It makes responsive layouts easier and lets you place elements the way you want without complex calculations.]]></description><link>https://www.heropy.dev/en/p/Ha29GI</link><guid isPermaLink="false">/en/p/Ha29GI</guid><category><![CDATA[CSS]]></category><category><![CDATA[Flex]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:31 GMT</pubDate></item><item><title><![CDATA[TanStack Query (React Query) Essentials]]></title><description><![CDATA[TanStack Query is a library that lets you manage data easily and efficiently, including fetching data from a server, caching data, and controlling the cache. It started under the name React Query, but from v4 its features were expanded so that it can also be used in other frameworks such as Vue and Svelte, and it was renamed TanStack Query.]]></description><link>https://www.heropy.dev/en/p/HZaKIE</link><guid isPermaLink="false">/en/p/HZaKIE</guid><category><![CDATA[TanStack Query]]></category><category><![CDATA[React Query]]></category><category><![CDATA[React]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:31 GMT</pubDate></item><item><title><![CDATA[React Context API Essentials]]></title><description><![CDATA[The React Context API is a way to share data between ancestor and descendant components in a project. This post explains its concepts and usage through examples.]]></description><link>https://www.heropy.dev/en/p/EdhHX2</link><guid isPermaLink="false">/en/p/EdhHX2</guid><category><![CDATA[React]]></category><category><![CDATA[Context API]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:31 GMT</pubDate></item><item><title><![CDATA[Tailwind CSS Core Patterns]]></title><description><![CDATA[Tailwind CSS is a CSS framework that minimizes writing separate CSS files and lets you style quickly by applying utility classes right in your HTML markup. It also lets you handle other styling, such as responsive design, dark mode, and hover states, inside your HTML.]]></description><link>https://www.heropy.dev/en/p/E67ZHS</link><guid isPermaLink="false">/en/p/E67ZHS</guid><category><![CDATA[React]]></category><category><![CDATA[CSS]]></category><category><![CDATA[Tailwindcss]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:31 GMT</pubDate></item><item><title><![CDATA[JS Class Core Patterns]]></title><description><![CDATA[JavaScript is a prototype-based language in terms of object-oriented programming. This post explains what a prototype is and looks at the core patterns of the class syntax added in ES2015.]]></description><link>https://www.heropy.dev/en/p/CPE3zl</link><guid isPermaLink="false">/en/p/CPE3zl</guid><category><![CDATA[JS]]></category><category><![CDATA[Classes]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:31 GMT</pubDate></item><item><title><![CDATA[Figma Essentials and Design Handoff (Dev Mode) Guide for Developers]]></title><description><![CDATA[From Figma's basic elements to components, variables, and prototypes, this post looks at Figma from a developer's point of view and shows how to use Dev Mode to turn designs into code.]]></description><link>https://www.heropy.dev/en/p/CHukYO</link><guid isPermaLink="false">/en/p/CHukYO</guid><category><![CDATA[Figma]]></category><category><![CDATA[Design Token]]></category><category><![CDATA[Component]]></category><category><![CDATA[Variable]]></category><category><![CDATA[Prototype]]></category><category><![CDATA[Dev Mode]]></category><category><![CDATA[MCP]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:31 GMT</pubDate></item><item><title><![CDATA[React Unit/E2E Test Automation with Vite/Next]]></title><description><![CDATA[Learn how to write unit tests with Vitest and Testing Library, mock APIs with MSW, and run E2E tests with Cypress in a React project.]]></description><link>https://www.heropy.dev/en/p/Bgimsk</link><guid isPermaLink="false">/en/p/Bgimsk</guid><category><![CDATA[React]]></category><category><![CDATA[Vitest]]></category><category><![CDATA[Testing Library]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:31 GMT</pubDate></item><item><title><![CDATA[The Complete Markdown Guide]]></title><description><![CDATA[This post looks at a variety of function patterns and concepts, from the basic usage of JavaScript functions to related terms and advanced techniques.]]></description><link>https://www.heropy.dev/en/p/B74sNE</link><guid isPermaLink="false">/en/p/B74sNE</guid><category><![CDATA[Markdown]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:31 GMT</pubDate></item><item><title><![CDATA[React Router Essentials (Data Mode)]]></title><description><![CDATA[With the React Router library, you can easily manage multiple pages and implement navigation in a React application. Let's look at the core concepts and usage of React Router, which supports features such as dynamic routing, nested routing, and several ways to navigate.]]></description><link>https://www.heropy.dev/en/p/9tesDt</link><guid isPermaLink="false">/en/p/9tesDt</guid><category><![CDATA[React]]></category><category><![CDATA[React Router]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:31 GMT</pubDate></item><item><title><![CDATA[Starting a React Project with Vite]]></title><description><![CDATA[Learn how to start a React project with the Vite.js build tool, with the setup for JavaScript and TypeScript projects explained separately.]]></description><link>https://www.heropy.dev/en/p/6iFzkB</link><guid isPermaLink="false">/en/p/6iFzkB</guid><category><![CDATA[React]]></category><category><![CDATA[Vite]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:30 GMT</pubDate></item><item><title><![CDATA[Understanding GitHub Flow Through Examples]]></title><description><![CDATA[GitHub Flow is a branching strategy built around GitHub, and it describes how you create and merge branches. Let's understand branching strategies through some simple GitHub Flow use cases.]]></description><link>https://www.heropy.dev/en/p/6hdJi6</link><guid isPermaLink="false">/en/p/6hdJi6</guid><category><![CDATA[Git]]></category><category><![CDATA[GitHub]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:30 GMT</pubDate></item><item><title><![CDATA[The srcset and sizes Attributes for HTML Images]]></title><description><![CDATA[To support images on the responsive web, you usually reach for the CSS media rule (`@media`), better known as a media query, and handling responsive images means thinking about everything from the viewport size to the resolution of the user's screen. With the `srcset` and `sizes` attributes of HTML `img`, though, you can hand most of that work to the browser, in the simplest case just by specifying image sizes.]]></description><link>https://www.heropy.dev/en/p/5Gl8hX</link><guid isPermaLink="false">/en/p/5Gl8hX</guid><category><![CDATA[HTML]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:30 GMT</pubDate></item><item><title><![CDATA[Vue Router Essentials]]></title><description><![CDATA[Vue Router is the official router library for Vue, and it supports many features for Vue applications, such as dynamic and nested routes, navigation control, HTML5 and hash modes, and scroll handling. In this post, let's look at the core features of Vue Router along with usage examples.]]></description><link>https://www.heropy.dev/en/p/2Hstmu</link><guid isPermaLink="false">/en/p/2Hstmu</guid><category><![CDATA[Vue]]></category><category><![CDATA[Vue Router]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:30 GMT</pubDate></item><item><title><![CDATA[The Complete Guide to CSS Animation]]></title><description><![CDATA[CSS Animation is a technique that adds animation effects by controlling an element's size, color, shape, and more with various CSS style properties. Because you can add dynamic effects to elements without JavaScript, you can implement animations with better performance.]]></description><link>https://www.heropy.dev/en/p/26YKpK</link><guid isPermaLink="false">/en/p/26YKpK</guid><category><![CDATA[CSS]]></category><category><![CDATA[Animation]]></category><category><![CDATA[Loader]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:30 GMT</pubDate></item><item><title><![CDATA[JS Resize Observer: Observing Element Size Changes]]></title><description><![CDATA[Resize Observer watches the size of an element and lets you provide an optimized callback to run when the element's size changes.]]></description><link>https://www.heropy.dev/en/p/0pVrDl</link><guid isPermaLink="false">/en/p/0pVrDl</guid><category><![CDATA[JS]]></category><category><![CDATA[Resize Observer]]></category><dc:creator><![CDATA[ParkYoungWoong]]></dc:creator><pubDate>Wed, 21 Oct 2026 05:50:30 GMT</pubDate></item></channel></rss>