<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>Rory Cai</title><description>Personal site and tech blog of Rory Cai: frontend, React Native, iOS / Android and developer productivity.</description><link>https://coiggahou2002.github.io/</link><language>en</language><item><title>Prompts, Skills, and MCP Will All Disappear. People Only Pay for Outcomes</title><link>https://coiggahou2002.github.io/blogs/pay-for-outcomes/</link><guid isPermaLink="true">https://coiggahou2002.github.io/blogs/pay-for-outcomes/</guid><description>Prompts, skills, hooks, plugins — they&apos;re all a transitional phase of AI apps. What survives is a marketplace of agents that sell nothing but results.</description><pubDate>Fri, 18 Sep 2026 16:34:00 GMT</pubDate></item><item><title>AI Won&apos;t Close the Gap Between People, and 7 Other Notes</title><link>https://coiggahou2002.github.io/blogs/recent-thoughts/</link><guid isPermaLink="true">https://coiggahou2002.github.io/blogs/recent-thoughts/</guid><description>AI won&apos;t narrow the gap between people. It does the opposite. It amplifies creativity and scales judgment, but it also amplifies stupidity and bias.</description><pubDate>Sun, 09 Aug 2026 06:00:35 GMT</pubDate></item><item><title>A New Less Release Broke Tailwind&apos;s @apply, and Tailwind Took the Blame</title><link>https://coiggahou2002.github.io/blogs/tailwind-less-compatibility/</link><guid isPermaLink="true">https://coiggahou2002.github.io/blogs/tailwind-less-compatibility/</guid><description>One of our large projects uses a micro-frontend architecture. The stack is SSR + Vue 3 + NestJS + Webpack4, the style preprocessor is Less, and the project also integrates Tailwind, which most of us use day to day to write styles quickly. Tailwind provides a bit of syntactic sugar called @apply that saves us some repetitive code. For example, in a Vue template we can write: The PM asks for a few…</description><pubDate>Sun, 14 Sep 2025 10:00:00 GMT</pubDate></item><item><title>How Long Is an Emoji, Really? A Deep Dive into Emoji Strings in UTF-16</title><link>https://coiggahou2002.github.io/blogs/deep-into-emoji/</link><guid isPermaLink="true">https://coiggahou2002.github.io/blogs/deep-into-emoji/</guid><description>In day-to-day frontend work we deal with emoji all the time. If you&apos;re new to this, you&apos;ve probably run into problems like these: You use split on a string that contains emoji, and it comes out broken You read .length on a string with emoji, and the number looks off Something goes wrong and weird question marks and boxes show up in your text. What are those? In practice, what we need is pretty…</description><pubDate>Wed, 16 Jul 2025 00:00:00 GMT</pubDate></item><item><title>How to Speed Up Frontend Project Builds</title><link>https://coiggahou2002.github.io/blogs/how-to-reduce-nuxt-project-compile-time/</link><guid isPermaLink="true">https://coiggahou2002.github.io/blogs/how-to-reduce-nuxt-project-compile-time/</guid><description>Don&apos;t put the build steps in the Dockerfile The Dockerfile should only be responsible for building the runtime image Cache nodemodules instead of installing every time; reuse it when package.json hasn&apos;t changed Use npm prune --production to remove devDependencies, which can cut the image size by more than half Use slim base images wherever possible, such as node:20-slim. If you don&apos;t even need…</description><pubDate>Sun, 08 Jun 2025 00:00:00 GMT</pubDate></item><item><title>Objective-C Learning Notes</title><link>https://coiggahou2002.github.io/blogs/app/objectivec/</link><guid isPermaLink="true">https://coiggahou2002.github.io/blogs/app/objectivec/</guid><description>Standard C data types work too Local variables are allocated on the stack, while objects are allocated on the heap Objective-C requires manual boxing/unboxing intValue is a method of the NSValue class Mutable / immutable Mutable / immutable %@ works like a printf format string; %@ stands for any object (it calls the object&apos;s description method, similar to toString in a Java class). The difference…</description><pubDate>Sat, 17 May 2025 00:00:00 GMT</pubDate></item><item><title>Some Notes on Cookies</title><link>https://coiggahou2002.github.io/blogs/http-cookie/</link><guid isPermaLink="true">https://coiggahou2002.github.io/blogs/http-cookie/</guid><description>What attributes should a cookie have? When a cookie has the HttpOnly attribute, it can only be sent over HTTP (or HTTPS) and can&apos;t be accessed by client-side JavaScript. This is an effective defense against cross-site scripting (XSS), because an attacker can&apos;t read an HttpOnly cookie by injecting malicious JavaScript. The Secure attribute says a cookie may only be sent over a secure HTTPS…</description><pubDate>Fri, 16 May 2025 00:00:00 GMT</pubDate></item><item><title>Nginx Notes</title><link>https://coiggahou2002.github.io/blogs/nginx/</link><guid isPermaLink="true">https://coiggahou2002.github.io/blogs/nginx/</guid><description>Below are common examples from Nginx HTTP configuration, covering core features like static file serving, reverse proxying, load balancing, and caching: Use this command to check whether the config is valid: If the config is fine, reload Nginx: In Nginx config, the servername directive specifies the domain names or IP addresses of a virtual host. It decides how Nginx routes traffic to different…</description><pubDate>Thu, 15 May 2025 00:00:00 GMT</pubDate></item><item><title>Batch-Generating WeChat Read&apos;s World Book Day Medals with Puppeteer</title><link>https://coiggahou2002.github.io/blogs/weread-medals-generator/</link><guid isPermaLink="true">https://coiggahou2002.github.io/blogs/weread-medals-generator/</guid><description>As everyone knows, April 23 is World Book Day, and WeChat Read ran another campaign this year: generating a unique medal for every user. How unique? Each medal carries two numbers. The one in the top-left is how many years the user has been on WeChat Read, and the one in the bottom-right is how many books they&apos;ve read over those years. For example, I&apos;ve been on it for 8 years and read 230 books,…</description><pubDate>Fri, 25 Apr 2025 00:00:00 GMT</pubDate></item><item><title>Piping Mobile WebView Console Logs into Native App Logs</title><link>https://coiggahou2002.github.io/blogs/hook-webview-console/</link><guid isPermaLink="true">https://coiggahou2002.github.io/blogs/hook-webview-console/</guid><description>In hybrid mobile development, we often embed RN or a WebView, and their JS runs in its own engine. For example: RN runs its JS in Hermes In iOS&apos;s WKWebView, JS runs on the JavaScriptCore engine In Android&apos;s WebView, JS runs in the V8 engine. By default, nothing printed through their console.log (or info/warn/error and the rest of the family) makes it into the native app&apos;s logs. So when a bug…</description><pubDate>Tue, 08 Apr 2025 00:00:00 GMT</pubDate></item><item><title>Fixing a Markdown Rendering Bug That Doubao Still Hasn&apos;t Fixed</title><link>https://coiggahou2002.github.io/blogs/markdown-emphasis-fix/</link><guid isPermaLink="true">https://coiggahou2002.github.io/blogs/markdown-emphasis-fix/</guid><description>In a recent project at work, we needed to parse Markdown generated by an LLM and render it in a WebView on mobile. Along the way we ran into a Markdown rendering problem: In the AI-generated Markdown, some bold text wasn&apos;t parsed correctly, so the raw asterisks showed up on the page. After digging in, we found the cause was a specific rule in the markdown-it parser, and we worked around it with a…</description><pubDate>Tue, 11 Mar 2025 13:00:00 GMT</pubDate></item><item><title>When a List Optimization Breaks Impression Tracking: The RN FlatList removeClippedSubviews Trap</title><link>https://coiggahou2002.github.io/blogs/rn-remove-clip-subview/</link><guid isPermaLink="true">https://coiggahou2002.github.io/blogs/rn-remove-clip-subview/</guid><description>In React Native, we often reach for the removeClippedSubviews prop on FlatList to squeeze more performance out of long lists. This innocent-looking optimization caused a data-tracking &quot;disaster&quot; on our team: list items that were nowhere near the viewport kept getting reported as &quot;seen&quot;. After a deep dive, we found the cause touched RN&apos;s view-tree management, the differences between iOS and…</description><pubDate>Wed, 22 Jan 2025 00:00:00 GMT</pubDate></item><item><title>import vs. import type: A Deep Dive Into How TypeScript Imports Get Compiled</title><link>https://coiggahou2002.github.io/blogs/importtype-import/</link><guid isPermaLink="true">https://coiggahou2002.github.io/blogs/importtype-import/</guid><description>At work, one page of a Nuxt 3 app that had been running reliably for a long time suddenly started returning a 500 Server Error in production, so a colleague and I started debugging it in local dev mode. While tracking down the error locally, we found the project throwing SyntaxError: The requested module myTypes does not provide an export named &apos;SomeType&apos;. It turned out to be caused by importing…</description><pubDate>Sun, 23 Jun 2024 00:00:00 GMT</pubDate></item><item><title>Make VS Code Snippets Shareable in Teams</title><link>https://coiggahou2002.github.io/blogs/share-vscode-snippets-among-team/</link><guid isPermaLink="true">https://coiggahou2002.github.io/blogs/share-vscode-snippets-among-team/</guid><description>Code snippets are templates that make it easier to enter repeating code patterns, such as loops or conditional-statements. VS Code allows users to define their own snippets in these levels: Global Snippets applies to every file regardless of the language they use Language-Level Snippets applies to specific language, like javascript.json configures snippets which only available to JavaScript etc.…</description><pubDate>Thu, 20 Jun 2024 00:00:00 GMT</pubDate></item><item><title>Git</title><link>https://coiggahou2002.github.io/blogs/git/</link><guid isPermaLink="true">https://coiggahou2002.github.io/blogs/git/</guid><description>A branch is just a pointer to a snapshot node Snapshot nodes form a directed acyclic graph The HEAD pointer points to the snapshot node that matches the current state of the working directory Working Directory Staging Area Once a file that git already knows about has been changed since the last commit, it enters this state. (A file git doesn&apos;t know about won&apos;t enter the Modified state even if it…</description><pubDate>Sun, 08 Oct 2023 00:00:00 GMT</pubDate></item><item><title>Kotlin Learning Notes</title><link>https://coiggahou2002.github.io/blogs/app/learn-kotlin/</link><guid isPermaLink="true">https://coiggahou2002.github.io/blogs/app/learn-kotlin/</guid><description>I&apos;ve been wanting to dig into the React Native source code lately, and starting from the Android side felt easier since I already know Java. But the project I maintain mixes Java and Kotlin, so I picked up some Kotlin along the way. I mostly learn it by comparing it with TypeScript. Short, Int, Long UShort, UInt, ULong Boolean String Float Double Comes in mutable and immutable flavors…</description></item></channel></rss>