<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Len Chou</title>
    <link>https://imzl.com/en/</link>
    <description>Wandering between business and product design</description>
    <language>en</language>
    <copyright>All rights reserved 2026, Len Chou</copyright>
    <lastBuildDate>Tue, 17 Mar 2026 03:17:51 GMT</lastBuildDate>
    <generator>Hexo</generator>
    <atom:link href="https://imzl.com/en/rss.xml" rel="self" type="application/rss+xml"/>
    <item>
      <title>
        <![CDATA[Internal Presentation & Document: A Brief Analysis of SEO Ranking Optimization Techniques]]>
      </title>
      <link>https://imzl.com/en/seo-ppt-document.html</link>
      <description>
        <![CDATA[<p>SEO has been making a comeback lately, especially in the going-global community, and many friends have been privately reaching out to me]]>
      </description>
      <author>Len Chou</author>
      <category domain="https://imzl.com/en/categories/operations/">Operations</category>
      <category domain="https://imzl.com/en/categories/share/">Sharing</category>
      <category domain="https://imzl.com/en/tag/seo/">SEO</category>
      <category domain="https://imzl.com/en/tag/pdf/">PDF</category>
      <pubDate>Fri, 23 Aug 2024 06:44:00 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>SEO has been making a comeback lately, especially in the going-global community, and many friends have been privately reaching out to me for advice. So here’s an SEO presentation I did internally at Wemai back in 2017, along with related documents. The content may be dated, but it covers the core principles of SEO that remain effective in practice today. I hope it helps those in need.</p><p>(Diyu was my work alias — don’t laugh…)</p><iframe src="https://cdn.imzl.com/docs/SEO%E5%91%A8%E4%BC%9A%E5%88%86%E4%BA%AB@%E5%9C%B0%E6%A6%86%EF%BC%88%E5%91%A8%E8%89%AF%E7%B2%A5%E5%87%89%EF%BC%89_2017.11.03.pdf" width="100%" height="2000px"></iframe><p><a href="https://cdn.imzl.com/docs/SEO%E5%91%A8%E4%BC%9A%E5%88%86%E4%BA%AB@%E5%9C%B0%E6%A6%86%EF%BC%88%E5%91%A8%E8%89%AF%E7%B2%A5%E5%87%89%EF%BC%89_2017.11.03.pdf">Download the SEO Presentation (PDF)</a></p><p>SEO Basic Standards Document: <a href="https://shimo.im/doc/aLMG4FtoLZ8JRoKC">https://shimo.im/doc/aLMG4FtoLZ8JRoKC</a></p><p>SEO Casual Discussion Notes: <a href="https://shimo.im/doc/7GVFl8rwU2snuY6X">https://shimo.im/doc/7GVFl8rwU2snuY6X</a></p>]]>
      </content:encoded>
    </item>
    <item>
      <title>Setting Up a Custom Domain for Bento.me Using Cloudflare Workers</title>
      <link>https://imzl.com/en/bento-add-domain.html</link>
      <description>
        <![CDATA[<p><a href="http://Bento.me">Bento.me</a> is a no-code platform for creating personal homepages, known for its elegant design and ease of us]]>
      </description>
      <author>Len Chou</author>
      <category domain="https://imzl.com/en/categories/experimentation/">Experimentation</category>
      <category domain="https://imzl.com/en/tag/Cloudflare/">Cloudflare</category>
      <category domain="https://imzl.com/en/tag/Bento/">Bento</category>
      <pubDate>Tue, 14 May 2024 21:00:00 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p><a href="http://Bento.me">Bento.me</a> is a no-code platform for creating personal homepages, known for its elegant design and ease of use.</p><p>But it has one drawback: <strong>it doesn’t support custom domains.</strong></p><p>Don’t worry though — this article will walk you through the simplest, zero-cost method to bind a custom domain to your <a href="http://Bento.me">Bento.me</a> page.</p><h2 id="1-Prerequisites">1. Prerequisites</h2><ol><li>You need to have a <a href="http://Bento.me">Bento.me</a> personal page</li><li>Register / prepare a Cloudflare account</li><li>Own an independent domain and transfer its DNS management to Cloudflare</li></ol><h2 id="2-Create-a-Cloudflare-Worker-Project">2. Create a Cloudflare Worker Project</h2><p>Enter the following command in your terminal to create a basic Cloudflare Worker:</p><p><code>npm create cloudflare@latest</code></p><p><img src="https://cdn.imzl.com/wp-content/uploads/2024/05/bento-add-domain.png" alt="Terminal operation"></p><p>Then follow the prompts in the terminal:</p><ul><li><p>In which directory do you want to create your application?</p><ul><li><strong>Default or custom — either is fine</strong></li></ul></li><li><p>What type of application do you want to create?</p><ul><li><strong>Select “Hello World” Worker</strong></li></ul></li><li><p>Do you want to use TypeScript?</p><ul><li><strong>Select NO (use the arrow keys to choose)</strong></li></ul></li><li><p>Do you want to use git for version control?</p><ul><li><strong>Select Yes</strong></li></ul></li><li><p>Do you want to deploy your application?</p><ul><li><strong>Select Yes (if this is your first time, it will automatically open a browser for login)</strong></li></ul></li></ul><p>Once complete, a folder will appear in the corresponding directory. Open it with a code editor such as Visual Studio Code.</p><h2 id="3-Set-Environment-Variables">3. Set Environment Variables</h2><ol><li>Edit the <code>wrangler.toml</code> file and add the following at the end:</li></ol><pre><code class="highlight ini"><span class="section">[vars]</span><span class="attr">BENTO_USERNAME</span> = <span class="string">&quot;len&quot;</span> <span class="comment"># Replace with your Bento page ID — mine is bento.me/len</span><span class="attr">BASE_URL</span> = <span class="string">&quot;https://bento.imzl.com&quot;</span> <span class="comment"># Replace with your custom domain</span></code></pre><ol start="2"><li>Create a <code>.dev.vars</code> file in the project root directory and paste the following:</li></ol><pre><code class="highlight ini"><span class="attr">BENTO_USERNAME</span>=<span class="string">&quot;len&quot;</span> <span class="comment"># Replace with your Bento page ID</span><span class="attr">BASE_URL</span>=<span class="string">&quot;http://127.0.0.1:8787&quot;</span></code></pre><h2 id="4-Create-the-Worker">4. Create the Worker</h2><ol><li>Edit the <code>/src/index.js</code> file and replace its contents with the following:</li></ol><pre><code class="highlight js"><span class="comment">/*</span><span class="comment"> * Setting up a custom domain for Bento.me</span><span class="comment"> * Author: len</span><span class="comment"> * Details: https://imzl.com/bento-add-domain.html</span><span class="comment"> * Original source: https://jayfranco.hashnode.dev/</span><span class="comment"> */</span><span class="comment">// Event listener</span><span class="title function_">addEventListener</span>(<span class="string">&#x27;fetch&#x27;</span>, <span class="function"><span class="params">event</span> =&gt;</span> &#123;  <span class="comment">// When a fetch event occurs, respond with the result of handleRequest</span>  event.<span class="title function_">respondWith</span>(<span class="title function_">handleRequest</span>(event.<span class="property">request</span>));&#125;);<span class="comment">// Parse response based on content type</span><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">parseResponseByContentType</span>(<span class="params">response, contentType</span>) &#123;  <span class="comment">// If there&#x27;s no content type, return the response as text</span>  <span class="keyword">if</span> (!contentType) <span class="keyword">return</span> <span class="keyword">await</span> response.<span class="title function_">text</span>();  <span class="comment">// Handle differently based on content type</span>  <span class="keyword">switch</span> (<span class="literal">true</span>) &#123;    <span class="keyword">case</span> contentType.<span class="title function_">includes</span>(<span class="string">&#x27;application/json&#x27;</span>):      <span class="comment">// If JSON, return as a JSON string</span>      <span class="keyword">return</span> <span class="title class_">JSON</span>.<span class="title function_">stringify</span>(<span class="keyword">await</span> response.<span class="title function_">json</span>());    <span class="keyword">case</span> contentType.<span class="title function_">includes</span>(<span class="string">&#x27;text/html&#x27;</span>):      <span class="comment">// If HTML, use HTMLRewriter to transform the response</span>      <span class="keyword">const</span> transformedResponse = <span class="keyword">new</span> <span class="title class_">HTMLRewriter</span>()        .<span class="title function_">on</span>(<span class="string">&#x27;body&#x27;</span>, &#123;          <span class="title function_">element</span>(<span class="params">element</span>) &#123;            <span class="comment">// Custom CSS and JS can be added to the HTML page here</span>            element.<span class="title function_">append</span>(              <span class="string">`</span><span class="string">                &lt;style&gt;</span><span class="string">                  // Add your custom CSS here</span><span class="string">                &lt;/style&gt;</span><span class="string">                `</span>,              &#123; <span class="attr">html</span>: <span class="literal">true</span> &#125;,            );            element.<span class="title function_">append</span>(              <span class="string">`</span><span class="string">                &lt;script&gt;</span><span class="string">                  // Add your custom JS here</span><span class="string">                &lt;/script&gt;</span><span class="string">                `</span>,              &#123; <span class="attr">html</span>: <span class="literal">true</span> &#125;,            );          &#125;,        &#125;)        .<span class="title function_">transform</span>(response);      <span class="comment">// Return the transformed response as text</span>      <span class="keyword">return</span> <span class="keyword">await</span> transformedResponse.<span class="title function_">text</span>();    <span class="keyword">case</span> contentType.<span class="title function_">includes</span>(<span class="string">&#x27;font&#x27;</span>):      <span class="comment">// If the content type is a font, return as ArrayBuffer</span>      <span class="keyword">return</span> <span class="keyword">await</span> response.<span class="title function_">arrayBuffer</span>();    <span class="keyword">case</span> contentType.<span class="title function_">includes</span>(<span class="string">&#x27;image&#x27;</span>):      <span class="comment">// If the content type is an image, return as ArrayBuffer</span>      <span class="keyword">return</span> <span class="keyword">await</span> response.<span class="title function_">arrayBuffer</span>()    <span class="attr">default</span>:      <span class="comment">// For all other content types, return as text</span>      <span class="keyword">return</span> <span class="keyword">await</span> response.<span class="title function_">text</span>();  &#125;&#125;<span class="comment">// Function to handle all requests</span><span class="keyword">async</span> <span class="keyword">function</span> <span class="title function_">handleRequest</span>(<span class="params">request</span>) &#123;  <span class="comment">// Extract the path from the request URL</span>  <span class="keyword">const</span> path = <span class="keyword">new</span> <span class="title function_">URL</span>(request.<span class="property">url</span>).<span class="property">pathname</span>;  <span class="comment">// By default, the URL is set to &quot;https://bento.me&quot; + path</span>  <span class="keyword">let</span> url = <span class="string">&#x27;https://bento.me&#x27;</span> + path;  <span class="comment">// If the path contains &#x27;v1&#x27;, change the URL to &#x27;https://api.bento.me&#x27; + path</span>  <span class="keyword">if</span> (path.<span class="title function_">includes</span>(<span class="string">&#x27;v1&#x27;</span>)) &#123;    url = <span class="string">&#x27;https://api.bento.me&#x27;</span> + path;  &#125;  <span class="comment">// If the URL is &quot;https://bento.me/&quot;, append the BENTO User ID</span>  <span class="keyword">if</span> (url === <span class="string">&#x27;https://bento.me/&#x27;</span>) &#123;    url = <span class="string">&#x27;https://bento.me/&#x27;</span> + <span class="variable constant_">BENTO_USERNAME</span>;  &#125;  <span class="comment">// Define basic headers for the fetch request</span>  <span class="keyword">let</span> headers = &#123;    <span class="string">&#x27;Access-Control-Allow-Origin&#x27;</span>: <span class="string">&#x27;*&#x27;</span>,    <span class="string">&#x27;Access-Control-Allow-Methods&#x27;</span>: <span class="string">&#x27;GET,HEAD,POST,OPTIONS&#x27;</span>,  &#125;;  <span class="comment">// Fetch the URL with the defined headers</span>  <span class="keyword">const</span> response = <span class="keyword">await</span> <span class="title function_">fetch</span>(url, &#123; headers &#125;);  <span class="comment">// Extract the content type from the response headers</span>  <span class="keyword">const</span> contentType = response.<span class="property">headers</span>.<span class="title function_">get</span>(<span class="string">&#x27;content-type&#x27;</span>);  <span class="comment">// Parse the response based on content type</span>  <span class="keyword">let</span> results = <span class="keyword">await</span> <span class="title function_">parseResponseByContentType</span>(response, contentType);  <span class="comment">// If the result is not an ArrayBuffer,</span>  <span class="comment">// replace all calls to the bento API with our BASE_URL</span>  <span class="comment">// This is a workaround for CORS errors</span>  <span class="keyword">if</span> (!(results <span class="keyword">instanceof</span> <span class="title class_">ArrayBuffer</span>)) &#123;    results = results.<span class="title function_">replaceAll</span>(<span class="string">&#x27;https://api.bento.me&#x27;</span>, <span class="variable constant_">BASE_URL</span>);  &#125;  <span class="comment">// Add the content type to the headers</span>  headers[<span class="string">&#x27;content-type&#x27;</span>] = contentType;  <span class="comment">// Return a new response with the results and headers</span>  <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">Response</span>(results, &#123; headers &#125;);&#125;</code></pre><ol start="2"><li>Navigate to the project folder in your terminal and run the code to preview:</li></ol><pre><code class="highlight yaml"><span class="string">npm</span> <span class="string">run</span> <span class="string">dev</span></code></pre><ol start="3"><li>Once everything looks good, deploy to production:</li></ol><pre><code class="highlight yaml"><span class="string">npm</span> <span class="string">run</span> <span class="string">deploy</span></code></pre><h2 id="5-Configure-the-Custom-Domain-in-Cloudflare">5. Configure the Custom Domain in Cloudflare</h2><ol><li>First, make sure the domain you want to bind has its DNS managed by Cloudflare.</li><li>Go to “Workers and Pages” and find the Worker project you just pushed.</li><li>Under “Settings - Triggers,” add your custom domain and wait for it to take effect.</li><li>Now you can visit <a href="https://bento.imzl.com">bento.imzl.com</a> to see your Bento page.</li></ol>]]>
      </content:encoded>
    </item>
    <item>
      <title>Crypto Reading List</title>
      <link>https://imzl.com/en/crypto-reading.html</link>
      <description>A curated reading list of crypto-related articles covering cyclical thinking across the entire crypto space. Recommended to be read in chronological order.</description>
      <author>Len Chou</author>
      <category domain="https://imzl.com/en/categories/crypto/">Crypto</category>
      <category domain="https://imzl.com/en/tag/crypto/">Crypto</category>
      <pubDate>Tue, 06 Feb 2024 23:00:00 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>Below is a curated reading list of crypto-related articles, originally copied from <a href="https://danromero.org/crypto-reading/">Dan Romero</a>’s blog. The titles were mostly in English — I’ve translated them into Chinese in the original post. Recommended to be read in chronological order:</p><h2 id="2008">2008</h2><ul><li><a href="https://bitcoin.org/bitcoin.pdf">Bitcoin: A Peer-to-Peer Electronic Cash System</a> — Where it all began. The Bitcoin whitepaper, written by someone under the pseudonym “Satoshi Nakamoto.”</li></ul><h2 id="2011">2011</h2><ul><li><a href="https://avc.com/2011/11/bitcoin/">Bitcoin</a> — by Fred Wilson</li></ul><h2 id="2013">2013</h2><ul><li><a href="https://cdixon.org/2013/12/12/coinbase">Coinbase</a> — by Chris Dixon</li><li><a href="https://cointelegraph.com/news/investor_chris_dixon_why_i_am_interested_in_bitcoin">Why I’m Interested in Bitcoin</a> — by Chris Dixon</li></ul><h2 id="2014">2014</h2><ul><li><a href="https://a16z.com/2014/01/21/why-bitcoin-matters-nyt/">Why Bitcoin Matters</a> — by Marc Andreessen</li></ul><h2 id="2016">2016</h2><ul><li><a href="https://medium.com/the-coinbase-blog/ethereum-is-the-forefront-of-digital-currency-5300298f6c75">Ethereum Is the Forefront of Digital Currency</a> — by Fred Ehrsam</li><li><a href="https://www.usv.com/writing/2016/08/fat-protocols/">Fat Protocols</a> — by Joel Monegro</li></ul><h2 id="2017">2017</h2><ul><li><a href="https://medium.com/@FEhrsam/value-of-the-token-model-6c65f09bcba8">Value of the Token Model</a> — by Fred Ehrsam</li><li><a href="https://blog.coinbase.com/a-beginners-guide-to-ethereum-46dd486ceecf">A Beginner’s Guide to Ethereum</a> — by Linda Xie</li><li><a href="https://medium.com/@VitalikButerin/the-meaning-of-decentralization-a0c92b76a274">The Meaning of Decentralization</a> — by Vitalik Buterin</li><li><a href="https://news.earn.com/thoughts-on-tokens-436109aabcbe">Thoughts on Tokens</a> — by Balaji Srinivasan</li><li><a href="https://cdixon.org/2017/05/27/crypto-tokens-a-breakthrough-in-open-network-design">Crypto Tokens: A Breakthrough in Open Network Design</a> — by Chris Dixon</li><li><a href="https://vitalik.eth.limo/general/2017/06/09/sales.html">Analyzing Token Sale Models</a> — by Vitalik Buterin</li><li><a href="http://blog.eladgil.com/2017/07/cryptocurrencys-netscape-moment.html">Cryptocurrency’s Netscape Moment</a> — by Elad Gil</li><li><a href="https://medium.com/@alokvasudev/permissionless-c66610ab2c38">Permissionless</a> — by Alok Vasudev</li><li><a href="https://thecontrol.co/the-slow-death-of-the-firm-1bd6cc81286b">The Slow Death of the Firm</a> — by Nick Tomaino</li><li><a href="http://blog.eladgil.com/2017/08/big-banks-and-blockchain.html">Big Banks and Blockchain</a> — by Elad Gil</li></ul><h2 id="2018">2018</h2><ul><li><a href="https://cdixon.org/2018/02/18/why-decentralization-matters">Why Decentralization Matters</a> — by Chris Dixon</li><li><a href="https://balajis.com/and-what-has-the-blockchain-ever-done-for-us/">And What Has the Blockchain Ever Done for Us?</a> — by Balaji Srinivasan</li><li><a href="https://medium.com/hackernoon/stablecoins-designing-a-price-stable-cryptocurrency-6bf24e2689e5">Stablecoins: Designing a Price-Stable Cryptocurrency</a> — by Haseeb Qureshi</li></ul><h2 id="2019">2019</h2><ul><li><a href="https://balajis.com/yes-you-may-need-a-blockchain/">Yes, You May Need a Blockchain</a> — by Balaji Srinivasan</li><li><a href="https://lindajxie.com/2019/08/07/the-future-of-decentralized-finance/">The Future of Decentralized Finance</a> — by Linda Xie</li><li><a href="https://www.youtube.com/watch?v=Dur918GqDIw">The Pseudonymous Economy</a> — by Balaji Srinivasan</li></ul><h2 id="2020">2020</h2><ul><li><a href="https://nakamoto.com/credible-neutrality/">Credible Neutrality as a Guiding Principle</a> — by Vitalik Buterin</li><li><a href="https://blog.coinbase.com/a-beginners-guide-to-decentralized-finance-defi-574c68ff43c4">A Beginner’s Guide to Decentralized Finance (DeFi)</a> — by Sid Coelho-Prabhu</li><li><a href="https://variant.fund/writing/the-ownership-economy-crypto-and-consumer-software">The Ownership Economy</a> — by Jesse Walden</li><li><a href="https://www.matthuang.com/bitcoin_for_the_open_minded_skeptic">Bitcoin for the Open Minded Skeptic</a> — by Matt Huang</li><li><a href="https://www.paradigm.xyz/2020/06/creators-communities-and-crypto">Creators, Communities, and Crypto</a> — by Fred Ehrsam</li><li><a href="https://medium.com/dragonfly-research/what-explains-the-rise-of-amms-7d008af1c399">What Explains the Rise of AMMs?</a> — by Haseeb Qureshi</li><li><a href="https://www.paradigm.xyz/2020/08/ethereum-is-a-dark-forest">Ethereum Is a Dark Forest</a> — by Dan Robinson and Georgios Konstantopoulos</li></ul><h2 id="2021">2021</h2><ul><li><a href="https://www.paradigm.xyz/2021/03/surviving-crypto-cycles">Surviving Crypto Cycles</a> — by Fred Ehrsam</li><li><a href="https://www.notboring.co/p/the-value-chain-of-the-open-metaverse">The Value Chain of the Open Metaverse</a> — by Packy McCormick</li><li><a href="https://research.paradigm.xyz/MEV">MEV and Me</a> — by Charlie Noyes</li><li><a href="https://variant.mirror.xyz/T8kdtZRIgy_srXB5B06L8vBqFHYlEBcv6ae2zR6Y_eo">NFTs Make the Internet Ownable</a> — by Jesse Walden</li><li><a href="https://cdixon.org/2021/02/27/NFTs-and-a-thousand-true-fans">NFTs and a Thousand True Fans</a> — by Chris Dixon</li><li><a href="https://linda.mirror.xyz/Vh8K4leCGEO06_qSGx-vS5lvgUqhqkCz9ut81WwCP2o">A Beginner’s Guide to DAOs</a> — by Linda Xie</li><li><a href="https://vitalik.eth.limo/general/2021/03/23/legitimacy.html">The Most Important Scarce Resource Is Legitimacy</a> — by Vitalik Buterin</li><li><a href="https://www.notboring.co/p/the-great-online-game">The Great Online Game</a> — by Packy McCormick</li><li><a href="https://balajis.com/p/add-crypto-to-indiastack">India and Crypto</a> — by Balaji Srinivasan</li><li><a href="https://www.notboring.co/p/own-the-internet">Own the Internet</a> — by Packy McCormick</li><li><a href="https://twitter.com/cdixon/status/1442201621266534402">Why Web3 Matters</a> — by Chris Dixon</li><li><a href="https://future.a16z.com/how-composability-unlocks-crypto-and-everything-else/">Composability Is Innovation</a> — by Linda Xie</li><li><a href="https://gubsheep.substack.com/p/the-strongest-crypto-gaming-thesis">The Strongest Crypto Gaming Thesis</a> — by gubsheep</li><li><a href="https://vitalik.eth.limo/general/2021/12/06/endgame.html">Endgame</a> — by Vitalik Buterin</li><li><a href="https://cobie.substack.com/p/trading-the-metagame">Trading the Metagame</a> — by Cobie</li><li><a href="https://balajis.com/mirrortable/">The Mirrortable</a> — by Balaji Srinivasan</li><li><a href="https://imzl.com/bitcoin-principle.html">Bitcoin Explained in Plain Language: How It Works</a> — by Zhang Yang</li></ul><h2 id="2022">2022</h2><ul><li><a href="https://www.1confirmation.com/2021-nft-annual-review">2021 NFT Annual Review</a> — by 1confirmation</li><li><a href="https://vitalik.eth.limo/general/2022/01/26/soulbound.html">Soulbound</a> — by Vitalik Buterin</li><li><a href="https://jacob.energy/hyperstructures.html">Hyperstructures</a> — by Jacob Horne</li><li><a href="https://www.varunsrinivasan.com/2022/01/11/sufficient-decentralization-for-social-networks">Sufficient Decentralization for Social Networks</a> — by Varun Srinivasan</li></ul><h2 id="2023">2023</h2><ul><li><a href="https://quail.ink/yishi/p/shi-bi-cheng-hou">Ten Coins to Rule Them All</a> — by Wang Yishi</li></ul>]]>
      </content:encoded>
    </item>
    <item>
      <title>Atomicals Mining Deployment and Wallet Management</title>
      <link>https://imzl.com/en/atomicals-mining.html</link>
      <description>A beginner-friendly tutorial on deploying the Atomicals mining program and managing wallets, helping you acquire Atomicals BTC inscription assets from scratch.</description>
      <author>Len Chou</author>
      <category domain="https://imzl.com/en/categories/crypto/">Crypto</category>
      <category domain="https://imzl.com/en/tag/atomicals/">Atomicals</category>
      <category domain="https://imzl.com/en/tag/mining/">Mining</category>
      <pubDate>Tue, 26 Dec 2023 17:13:00 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="Deployment">Deployment</h2><ol><li>Install <a href="https://nodejs.org/en">Node.js</a></li><li><code>git clone https://github.com/atomicals/atomicals-js.git</code></li><li><code>cd atomicals-JavaScript</code></li><li><code>npm install -g typescript</code></li><li><code>npm run build</code></li><li><code>npm install -g yarn</code></li><li><code>yarn install</code></li><li><code>yarn cli wallet-init</code> // This is the command to create a wallet</li></ol><p>The last step creates a wallet. After running the command, a <code>wallet.json</code> file will be generated in the folder, containing your mnemonic phrase and private key. Make sure to back up this file securely.</p><p>Once the wallet is created, two addresses are automatically generated: Primary Address and Funding Address.</p><p><strong>Primary</strong>: Used to receive Atomicals ecosystem assets.<br><strong>Funding</strong>: A transit wallet used during the minting (mining) process. Typically, you deposit the required amount of BTC into the Funding address for minting the corresponding assets.</p><h2 id="Common-Commands">Common Commands</h2><h3 id="Minting-FT-Command">Minting FT Command:</h3><p><code>yarn cli mint-dft dmint --satsbyte 30</code></p><p><code>yarn cli mint-dft quark --satsbyte=100</code></p><p><code>dmint</code> and <code>quark</code> are token names — replace them with the corresponding FT asset name.<br><code>satsbyte</code> sets the miner fee. Setting it to 100 means minting at a rate of 100 sats/KB.</p><h3 id="Minting-Image-NFT-Command">Minting Image NFT Command:</h3><p><code>yarn cli mint-nft &quot;\punk0000.png&quot; --satsbyte 30 --satsoutput 1000 --bitworkc 233</code></p><h3 id="Checking-Balance">Checking Balance:</h3><p><code>npm run cli balances</code></p>]]>
      </content:encoded>
    </item>
    <item>
      <title>Starknet Early Community Member Program Application Guide</title>
      <link>https://imzl.com/en/starknet-ecmp.html</link>
      <description>A guide to the Starknet Early Community Member Program (ECMP), helping every member of the Starknet community quickly understand the program and how to apply.</description>
      <author>Len Chou</author>
      <category domain="https://imzl.com/en/categories/crypto/">Crypto</category>
      <category domain="https://imzl.com/en/tag/starknet/">Starknet</category>
      <category domain="https://imzl.com/en/tag/communal/">Community</category>
      <pubDate>Wed, 01 Nov 2023 13:00:00 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>Starknet, a rapidly rising name in the ETH L2 space, is now offering unprecedented opportunities to its community members through its newly launched Early Community Member Program (ECMP). This program is not just about technical contributions — it’s about recognizing every individual who has helped advance the Starknet ecosystem.</p><p>As a staunch Starknet supporter, I believe this is a unique opportunity for community members — whether developers, content creators, event organizers, or active participants in technical discussions — to be recognized and rewarded.</p><h2 id="Application-Process-and-Timeline">Application Process and Timeline</h2><p>Applications open on October 30, 2023 and close on November 23. The review committee will make its decisions by December 29. Interested individuals and projects should submit their applications within this period.</p><h2 id="Who-Can-Apply">Who Can Apply?</h2><p>The ECMP is open to individuals who have actively contributed to the Starknet ecosystem. Whether through technical discussions, organizing events, publishing branded content, or any other means of adding vitality and resources to the ecosystem — all such individuals should consider applying.</p><h2 id="Evaluation-Criteria">Evaluation Criteria</h2><p>The evaluation criteria include impact, significance, effort, and originality. This means it’s not just about lines of code — it also encompasses your impact on the community, the importance of your work to the project, the effort you’ve put in, and the originality of your contributions.</p><h2 id="Application-Process">Application Process</h2><p>Both projects and individuals need to submit applications through the provided link, including their Telegram ID, email address, and Starknet wallet address. Each project and individual will be evaluated by the committee.</p><p>Application link: <a href="https://ecmp.starknet.io/form-individual">https://ecmp.starknet.io/form-individual</a></p><p>Starknet official announcement: <a href="https://community.starknet.io/t/announcing-the-early-community-member-program/102092">https://community.starknet.io/t/announcing-the-early-community-member-program/102092</a></p><h2 id="Important-Notes">Important Notes</h2><p>It is important to note that sanctioned individuals, residents of sanctioned countries, and US-affiliated persons are not eligible to participate.</p><p>This program marks a significant step in the growth and development of the Starknet community. It not only rewards the unsung heroes but also encourages more people to join and contribute to the ecosystem. If you are a dedicated Starknet supporter, don’t miss this opportunity.</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>How to Bypass the Annoying hCaptcha Verification</title>
      <link>https://imzl.com/en/disabling-hcaptcha.html</link>
      <description>Learn how to bypass hCaptcha — simplify the human verification process and avoid frequent, pointless image challenges. Read on to easily bypass hCaptcha verification.</description>
      <author>Len Chou</author>
      <category domain="https://imzl.com/en/categories/experimentation/">Experimentation</category>
      <category domain="https://imzl.com/en/tag/skill/">Tips</category>
      <category domain="https://imzl.com/en/tag/hcaptcha/">hcaptcha</category>
      <category domain="https://imzl.com/en/tag/captcha/">CAPTCHA</category>
      <pubDate>Tue, 16 May 2023 20:15:00 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="What-Is-hCaptcha">What Is hCaptcha?</h2><p>hCaptcha is a human verification service similar to Google reCAPTCHA. It is designed to identify and distinguish human users from bots, and to help prevent common web automation attacks such as DoS, malicious bot attacks, and excessive web scraping.</p><p>From my own experience, I’m not sure how effective hCaptcha is at blocking bots, but it certainly causes a great deal of inconvenience for actual humans. So let’s figure out a way to bypass hCaptcha and its frequent, pointless image verification challenges:</p><h2 id="Bypass-hCaptcha-via-the-Accessibility-Service">Bypass hCaptcha via the Accessibility Service</h2><ol><li><p>Sign up for the accessibility service through <a href="https://dashboard.hcaptcha.com/signup?type=accessibility">this link</a>. Please use a valid, active email address.</p></li><li><p>Check your inbox and click the “Get Accessibility Cookie” button in the email. The link should look something like this:<br><code>https://accounts.hcaptcha.com/verify_email/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx</code></p></li><li><p>Obtain the hCaptcha Cookie via the link</p></li></ol><ul><li>Clicking the button will redirect you to the hCaptcha settings page.</li><li>Click the “Set Cookie” button, and wait until the text “Cookie set.” appears below the button — then you’re done.</li></ul><p>The next time you encounter an hCaptcha challenge, you only need to click the verification checkbox — no more annoying image puzzles.</p><p>[Note] hCaptcha has actually documented their accessibility service as well. <a href="https://www.hcaptcha.com/accessibility">See the details here</a>.</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>Bitcoin Explained in Plain Language</title>
      <link>https://imzl.com/en/bitcoin-principle.html</link>
      <description>
        <![CDATA[<p>While organizing my Crypto materials recently, I came across this article by Zhang Yang. It’s possibly the best plain-language explanatio]]>
      </description>
      <author>Len Chou</author>
      <category domain="https://imzl.com/en/categories/crypto/">Crypto</category>
      <category domain="https://imzl.com/en/tag/Bitcoin/">Bitcoin</category>
      <category domain="https://imzl.com/en/tag/finance/">Finance</category>
      <category domain="https://imzl.com/en/tag/currency/">Currency</category>
      <category domain="https://imzl.com/en/tag/Reprint/">Reprint</category>
      <pubDate>Thu, 25 Nov 2021 00:00:00 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>While organizing my Crypto materials recently, I came across this article by Zhang Yang. It’s possibly the best plain-language explanation of Bitcoin’s principles and mechanisms ever written, so I’m reposting it here to share.</p><p>This article is intended as a popular science piece. It uses analogies to explain Bitcoin’s fundamental principles without delving into the granular details of algorithms and protocols.</p><p>The article presents a fictional village called “Bitcoin Village” and tells a story, step by step, explaining Bitcoin’s motivation, the problems it solves, and the objectives and design of its key components.</p><h2 id="Bitcoin-Village-and-the-Barter-System">Bitcoin Village and the Barter System</h2><p>Once upon a time, there was a small village called Bitcoin Village, home to a few hundred households. The village was virtually isolated from the outside world, living a self-sufficient existence. Without large-scale trade, the villagers had always relied on barter — Old Zhang would trade a sack of flour for one of Old Li’s sheep, and Mrs. Wang would swap a basket of wild fruit for two feet of Mrs. Liu’s cloth. The villagers had been living this simple life all along.</p><p><img src="https://img.imzl.com/wp-content/uploads/2021/11/1637783546-bitcoin-mechanism-01.png" alt=""></p><h2 id="Commodity-Money">Commodity Money</h2><p>One day, the villagers decided that barter was just too inconvenient, so the entire village gathered for a meeting to discuss how to solve this problem. Someone proposed using something easily divisible and rare — gold, for example — as a medium of exchange. They would create a conversion table mapping goods to gold: one gram of gold equals one sheep, one gram of gold equals one sack of flour, and so on. Now Old Zhang no longer had to lug a heavy sack of flour all the way to Old Li’s house to trade for a sheep. He could simply pull out a gram of gold, head to Old Li’s, and lead a sheep home. Old Li could then use that gram of gold to buy a sack of flour from anyone willing to sell, or trade it for anything else of equivalent value.</p><p>Thus Bitcoin Village entered the era of commodity money.</p><p><img src="https://img.imzl.com/wp-content/uploads/2021/11/1637783620-bitcoin-mechanism-02.png" alt=""></p><h2 id="Symbolic-Money">Symbolic Money</h2><p>But it didn’t last. Before long, the drawbacks of commodity money became apparent. Gold mines near Bitcoin Village were scarce, and mining and smelting gold was extremely time-consuming and labor-intensive. Meanwhile, gold was constantly being lost to wear, misplacement, or deliberate hoarding. The villagers gathered once again to brainstorm a solution. Someone said, “We don’t actually need to use real gold. Just take any piece of paper, write ‘one gram of gold’ on it, and as long as everyone in the village agrees that this piece of paper equals one gram of gold, problem solved.” Everyone nodded in agreement, but a new issue immediately arose: real gold requires mining and smelting, mines are limited, and the process costs time and resources — no one can conjure vast quantities of gold out of thin air. But writing on paper? As long as you have enough paper and ink, you can write as much as you want. It would devolve into a contest of who has more paper at home — before you know it, ten thousand sheets might buy you just one sheep (this is, in fact, what economics calls inflation).</p><p>Good point, everyone thought. But then someone proposed a solution: these notes would only be valid if written by the village elder — a man of great respect whose handwriting everyone recognized. The elder would write out a number of notes and distribute them to each household based on their gold reserves. For example, if Old Zhang had two hundred grams of gold, the elder would issue him two hundred notes, each reading “one gram of gold,” and take Old Zhang’s gold as collateral. In this way, the elder collected all the village’s gold and issued equivalent paper notes. The villagers could now use these notes as currency, and since everyone recognized the elder’s handwriting, no one else could forge them. If anyone’s notes became too worn, they could exchange them for fresh ones at the elder’s house. Furthermore, the elder promised that anyone wishing to convert back to real gold need only return the notes and receive the equivalent amount. Since the gold amount recorded on the notes matched the actual gold stored at the elder’s house, as long as the strict principle of “destroy old notes, issue new ones” was followed, every valid note could always be redeemed for its corresponding amount of real gold.</p><p>Thus Bitcoin Village entered the era of symbolic money (paper currency). The village elder assumed the roles of both government and bank.</p><p><img src="https://img.imzl.com/wp-content/uploads/2021/11/1637783682-bitcoin-mechanism-03.png" alt=""></p><h2 id="Centralized-Virtual-Currency">Centralized Virtual Currency</h2><p>A few more years passed. The village elder, exhausted from the daily grind of verifying old notes, writing new ones, and meticulously maintaining all the records, eventually worked himself to death.</p><p>Bitcoin Village convened another general assembly to discuss what to do. The elder’s son, Ergouzi (literally “Second Doggy”), volunteered to take up his father’s pen and shoulder the responsibility of currency issuance. This young village leader was clever. After a few days of work, he realized he didn’t actually need to write all those paper notes. He could simply do this: have the villagers turn in all their paper notes, destroy them, and instead record each household’s balance in a ledger. From then on, if someone wanted to make a payment — say Old Zhang wanted to pay Old Li one gram of gold for a sheep — the two would simply call Ergouzi, explain the transaction, and Ergouzi would open his ledger, verify that Old Zhang had at least one gram of gold on record, subtract one gram from Old Zhang’s account, and add one gram to Old Li’s. Transaction complete. Upon hearing Ergouzi’s confirmation over the phone, Old Li could confidently let Old Zhang take the sheep.</p><p>Thus Bitcoin Village entered the era of centralized virtual currency. No villager needed to make physical payments anymore; the payment process became nothing more than number changes in the ledger maintained by Ergouzi.</p><p><img src="https://img.imzl.com/wp-content/uploads/2021/11/1637783714-bitcoin-mechanism-04.png" alt=""></p><h2 id="Distributed-Virtual-Currency">Distributed Virtual Currency</h2><p>Ergouzi was clever, but sometimes too clever for his own good. One day, staring at the ledger, he thought: “The entire village’s wealth is whatever I say it is — couldn’t I just…” On impulse, he secretly transferred ten grams of gold from Old Zhang’s account to his own.</p><p>He thought it was the perfect crime, but Old Zhang happened to keep his own records. One day, when Old Zhang tried to make a payment, Ergouzi told him his account was empty. Old Zhang checked his own books — he clearly still had ten grams — and went to confront Ergouzi. The discrepancy revealed the unauthorized transfer.</p><p>The scandal broke wide open. Ergouzi’s impeachment was inevitable, but the incident also exposed a fundamental flaw in having the ledger concentrated in one person’s hands:</p><ul><li>The entire system depends on the personal integrity of the ledger keeper. If this person breaks the rules and arbitrarily alters the ledger, the entire monetary system collapses.</li><li>If this person’s house catches fire or the ledger is stolen, it would be equally devastating to the entire system.</li></ul><p>Just as everyone was at a loss, a reclusive scientist in the village named Satoshi Nakamoto took the stage. He told everyone he had designed a virtual currency system called Bitcoin that didn’t rely on any central authority, and it could solve all the problems above. Then he calmly laid out his plan.</p><p>Let’s see how Satoshi designed this system.</p><h2 id="Infrastructure-Setup">Infrastructure Setup</h2><p>Satoshi first announced that the existing ledger system would need the following modifications:</p><ol><li>The ledger would no longer record each villager’s balance. Instead, it would only record individual transactions — specifically, the payer, payee, and amount of each transaction. As long as the ledger’s initial state is established and every transaction record is reliable and time-ordered, each person’s current balance can be calculated.</li><li>The ledger would change from private to public. Any villager who wanted it could obtain the complete current ledger, containing every transaction record from the ledger’s creation to the present.</li></ol><p>The moment he said this, the crowd erupted. The first point was fine, but the second was nearly unacceptable — the ledger records every villager’s transactions, wouldn’t this expose everyone’s privacy?</p><p>Satoshi remained calm and produced a pair of peculiar objects.</p><h2 id="Identity-and-Signature-Mechanism-Public-Key-Cryptography">Identity and Signature Mechanism (Public Key Cryptography)</h2><p>Satoshi told everyone not to panic. Under his system, no one would transact using their real identity. Instead, each person would use a unique pseudonym.</p><p>He showed the two items in his hands, calling them the “secret stamp” and the “stamp scanner.” He would give every household one of each. Their functions:</p><ul><li>The secret stamp can imprint a mark on paper. Each stamp’s imprint contains a string of characters unique to the entire village, but invisible to the naked eye. Nor can the stamp be reverse-engineered by examining its imprint.</li><li>The stamp scanner can scan a stamped mark, read the hidden information, and display a string of characters on its LCD screen.</li></ul><p>With these two ingenious devices, villagers could transact without revealing their true identities, and the hidden character string would serve as each household’s pseudonym. The precise mechanism for using stamps and scanners in transactions is detailed below.</p><h3 id="Establishing-a-Virtual-Mining-Organization-Mining-Groups">Establishing a Virtual Mining Organization (Mining Groups)</h3><p>Next, Satoshi recruited virtual miners from across the village. The requirements:</p><ul><li>Miners work in groups; a group can be a single household or several households combined.</li><li>Being a miner doesn’t affect normal currency usage.</li><li>Miners must dedicate some time each day to Bitcoin “mining” activities, but unlike gold mining, virtual miners don’t need to go into the field with tools — they can work from home.</li><li>Miners have a certain probability of earning a reward; the more effort put into mining, the higher the probability.</li><li>Miners can quit at any time, and new miners can join at any time.</li></ul><p>Before long, about one-fifth of the villagers joined the mining organization, forming seven groups.</p><h2 id="Creating-the-Initial-Ledger-Genesis-Block">Creating the Initial Ledger (Genesis Block)</h2><p>Next, Satoshi announced that based on Ergouzi’s ledger, all collateralized gold would be returned to each villager according to the recorded balances. Ergouzi’s ledger would then be permanently destroyed.</p><p>Satoshi then produced a new ledger. On the first page, he recorded several transactions. Notably, the “payer” column for all these entries read “System,” while the payees were the hidden character strings corresponding to each household’s stamp — representing the system’s initial allocation of a small number of bitcoins to each household. The amounts were very small, just a few coins each, and some unlucky households didn’t receive any at all.</p><p>Satoshi then said: since there are very few bitcoins in circulation right now, everyone can go back to using gold as currency for the time being. Since I’m not the village leader, I have no authority to force anyone to accept Bitcoin — everyone can decide for themselves. But as bitcoins flow through transactions and mining activity continues, the supply will gradually increase.</p><h2 id="Payment-and-Transactions">Payment and Transactions</h2><p>After all this groundwork, we finally arrive at the main event: how payments work in this system. Let’s use Old Zhang paying Old Li 10 bitcoins as an example.</p><h3 id="The-Payer-Signs-the-Transaction-Slip">The Payer Signs the Transaction Slip</h3><p>To pay 10 bitcoins, Old Zhang first asks Old Li for his identifier string — say “ABCDEFG.” Old Zhang’s own identifier is, say, “HIJKLMN.” Old Zhang writes a slip reading “HIJKLMN pays 10 bitcoins to ABCDEFG,” stamps it with his secret stamp, and hands the slip to Old Li. Additionally, to facilitate tracing the origin of these funds, the slip must note where this money came from and which ledger page recorded the source transaction. In this case, Old Zhang’s 10 bitcoins came from the system’s initial allocation, recorded on the ledger’s first page.</p><p><img src="https://img.imzl.com/wp-content/uploads/2021/11/1637783753-bitcoin-mechanism-05.png" alt=""></p><h3 id="The-Payee-Verifies-the-Signer">The Payee Verifies the Signer</h3><p>Upon receiving the slip, Old Li needs to confirm it was indeed signed by “HIJKLMN” (i.e., Old Zhang). This isn’t difficult. The slip must bear a secret stamp. Old Li takes out his stamp scanner, scans the stamp, and if the characters displayed on the LCD match the payer’s identifier (in this case, “HIJKLMN”), the signature is confirmed. Thanks to the secret stamp mechanism, no one else can forge a stamp, and anyone can verify whether the signer matches the stated payer simply by scanning.</p><h3 id="The-Payee-Confirms-the-Payer’s-Balance">The Payee Confirms the Payer’s Balance</h3><p>So far, the system still has a problem. Through the secret stamp, the payee can confirm the payer indeed signed the slip, but cannot independently verify whether the payer has sufficient funds. In the previous centralized system, Ergouzi was responsible for checking balances and notifying payees whether transactions were valid. Now that Ergouzi’s been fired, who handles accounting and transaction validation?</p><p>As mentioned earlier, Satoshi designed this as a distributed currency system that doesn’t rely on any central figure. The entity that ultimately bears this responsibility is the mining organization mentioned previously. Old Zhang, Old Li, and every other villager using Bitcoin for transactions all depend on the miners’ work to complete their transactions.</p><h2 id="The-Miners’-Work">The Miners’ Work</h2><p>The miners’ work is the core of the entire system and also its most complex part. Let’s walk through their tasks and objectives step by step.</p><h3 id="Mining-Tools">Mining Tools</h3><p>As the saying goes, “A craftsman must first sharpen his tools.” While Bitcoin miners don’t need pickaxes, shovels, or headlamps, they do need some essential equipment.</p><p><strong>Initial ledger.</strong> Each group first makes their own copy of the initial ledger, which has only one page recording the system’s first allocation.</p><p><strong>Blank ledger pages.</strong> Each group has a supply of blank ledger pages. Each page contains only the ledger structure with no content filled in — the rules for writing content are described below. Here’s what a blank ledger page looks like; the meaning of each field will be explained later.</p><p><img src="https://img.imzl.com/wp-content/uploads/2021/11/1637783804-bitcoin-mechanism-06.png" alt=""></p><p><strong>Code generator (hash function).</strong> Satoshi also distributed several code generators to each mining group. This device is remarkable: insert a completed ledger page and the machine automatically prints a 256-character string of &quot;0&quot;s and &quot;1&quot;s in the “This Page’s ID” field. The truly magical properties of the code generator are:</p><ul><li>The generated ID depends solely on the content written on the ledger page — it’s independent of who wrote it, the handwriting style, the time of writing, and other factors.</li><li>Ledger pages with identical content always produce the same ID, but changing even a single character produces a completely different ID.</li><li>When printing an ID, the code generator also requires all transaction slips referenced on the page to be inserted. The machine scans for consistency between the transaction slips and the written entries, especially the secret stamps. If any stamp doesn’t match its stated payer, the machine refuses to print.</li><li>When a pre-printed ledger page is inserted, the machine verifies whether the ID was genuinely machine-printed and whether the ID matches the content. The ID cannot be forged.</li><li><strong>Transaction slip mailbox.</strong> Each mining group must hang a collection box at their door for receiving transaction slips.</li><li><strong>Bulletin board.</strong> Each mining group also needs a bulletin board for posting public notices.</li></ul><p>With these tools in hand, the mining organization can get to work.</p><h3 id="Collecting-Transaction-Slips">Collecting Transaction Slips</h3><p>Satoshi established that anyone initiating a transaction must not only give the transaction slip to the payee but also make several copies and deliver them to every mining group’s mailbox.</p><p>Mining groups periodically collect all accumulated transaction slips from their mailboxes.</p><h3 id="Filling-Out-the-Ledger">Filling Out the Ledger</h3><p>The group then takes a blank ledger page, writes these transactions into the “Transaction List” section, finds the last page of their current ledger, and copies that page’s ID into the “Previous Page ID” field. Note there’s also a “Lucky Number” field — they can fill in any number they like, such as 12345. Then they insert the page into the code generator, which prints an ID. One ledger page is now complete.</p><p>If you thought the miners’ job was that simple, you’d be sorely mistaken. Satoshi imposed a fiendish rule: <strong>a ledger page is only valid if the first 10 digits of its ID are all zeros.</strong></p><p>Based on what we know about the code generator, the only way to change the ID is to change the page’s content. The “Transaction List” and “Previous Page ID” can’t be arbitrarily modified, so the only option is to change the Lucky Number. Thus, to produce a valid ledger page, miners must repeatedly copy out ledger pages with different Lucky Numbers, inserting each one into the code generator. If the resulting ID doesn’t meet the requirement, that page is wasted. They repeat this process until a valid ID is generated.</p><p>We know that if each digit of the ID is random, miners must try, on average, over 1,000 different Lucky Numbers to get one valid ID.</p><p>So why would miners relentlessly grind away at this seemingly meaningless task? Remember the rewards mentioned earlier — that’s their motivation. Satoshi decreed: <strong>the first transaction on every ledger page is “The system pays this group 50 bitcoins.”</strong> In other words, if you generate a valid ledger page and it’s accepted by all mining groups, this transaction is also accepted, and your mining group earns 50 bitcoins.</p><p>This is why miners are called miners, and why, as mentioned earlier, the supply of bitcoins gradually increases through transactions and mining activity. Below is an example of the mining process, where the group’s public Bitcoin address is “UVWXYZ.”</p><p><img src="https://img.imzl.com/wp-content/uploads/2021/11/1637783852-bitcoin-mechanism-07.png" alt=""></p><p>When the Lucky Number reached “533,” the system generated a valid ledger page.</p><h3 id="Confirming-the-Ledger">Confirming the Ledger</h3><p>When a mining group is lucky enough to produce a valid ledger page, they must immediately notify the other groups to get their work confirmed and earn their reward. As mentioned, there are currently seven mining groups in the village, so the lucky group must transcribe six copies and rush them to the other six groups for confirmation.</p><p>Satoshi decreed that when any group receives a ledger page from another group, they must immediately pause their own mining work and perform verification.</p><p>Three things need to be confirmed:</p><ol><li>The page’s ID is valid.</li><li>The previous page referenced is valid.</li><li>The transaction list is valid.</li></ol><p>For the first check — this is straightforward. Simply insert the received page into the code generator for verification. If it passes, the ID is valid.</p><p>For the second check — compare the “Previous Page ID” on the received page against the last page ID in this group’s own ledger. If they match, it’s confirmed. If not, trace backward through the existing ledger to find the matching page. If no matching “Previous Page ID” can be found at all, the group discards the received page and refuses confirmation.</p><p>Note that this mechanism ensures that if all groups hold the same set of ledger pages, they can all assemble them in the same order. Since each page’s ID depends on the previous page’s ID, the code generator’s mechanism guarantees that the relative ordering of all valid ledger pages is consistent across every group (there may be branches, but no loops — more on this later).</p><p><img src="https://img.imzl.com/wp-content/uploads/2021/11/1637783887-bitcoin-mechanism-08.png" alt=""></p><p>Finally, confirming the transaction list’s validity means verifying that each payer in every transaction has sufficient balance. Since each transaction includes information about where the funds came from, along with the ID of the ledger page recording the source transaction — for example, HIJKLMN wants to pay ABCDEFG 10 bitcoins and notes that these 10 bitcoins came from a previous payment from OPQRST to HIJKLMN — the verification process first confirms whether this earlier transaction exists, and then checks whether HIJKLMN hasn’t already spent those 10 bitcoins elsewhere. Once all this is confirmed, the transaction’s validity is established.</p><p>The first transaction is the 50-bitcoin system reward to the group that produced the page — everyone accepts this by default. For the remaining transactions, the tracing method above can confirm whether HIJKLMN truly has 10 bitcoins to pay ABCDEFG.</p><p>If all the above verifications pass, the group accepts the ledger page as valid, appends it to their main ledger, abandons their current work-in-progress, and continues future mining based on this updated main ledger.</p><h3 id="Ledger-Confirmation-Feedback">Ledger Confirmation Feedback</h3><p>For the mining group that sent out the page: if they subsequently receive a page from another group whose “Previous Page ID” is the ID of the page they sent out, that means their work has been accepted — because another group is already building on top of it. At this point, they can roughly consider their 50 bitcoins earned.</p><p>Additionally, whenever a group generates a new valid page or confirms another group’s page, they post the latest accepted transactions on their bulletin board. Payees who see their transaction acknowledged by the various groups can be fairly confident the money has arrived in their account, and they can reference this transaction as the source of funds in future payments.</p><p>This is the complete Bitcoin payment system. Let’s now analyze why this system can sustain itself and what risks it may face.</p><h2 id="Analysis-of-the-Operating-Mechanism">Analysis of the Operating Mechanism</h2><p>Although the basic rules of Bitcoin have been explained, the villagers still had many questions. So Satoshi held a special Q&amp;A session to address common concerns. Below is a summary of the most frequently raised issues.</p><h2 id="Core-Q-A">Core Q&amp;A</h2><h3 id="What-if-two-valid-ledger-pages-are-received-simultaneously">What if two valid ledger pages are received simultaneously?</h3><p>Note that in the mechanism described above, mining groups work in parallel. It’s entirely possible that a group receives two different ledger pages, both based on the current last page of the group’s main ledger, and both perfectly valid. What then?</p><p>Satoshi explained that groups should not organize the ledger linearly but rather as a tree structure. At any given time, the longest branch serves as the main ledger, while other branches are preserved. For example, if a group simultaneously receives valid pages A and B, they should organize them as a fork, like this:</p><p><img src="https://img.imzl.com/wp-content/uploads/2021/11/1637783962-bitcoin-mechanism-09.png" alt=""></p><p>The black line represents the current main chain. At this point, either page can be chosen as the main branch — let’s say A:</p><p><img src="https://img.imzl.com/wp-content/uploads/2021/11/1637783996-bitcoin-mechanism-10.png" alt=""></p><p>If a new page is produced based on A, the main chain extends:</p><p><img src="https://img.imzl.com/wp-content/uploads/2021/11/1637784030-bitcoin-mechanism-11.png" alt=""></p><p>If this trend continues, it means everyone is essentially working off A as the main chain, and B will be forgotten. But it’s also possible that B suddenly becomes the longer branch:</p><p><img src="https://img.imzl.com/wp-content/uploads/2021/11/1637784087-bitcoin-mechanism-12.png" alt=""></p><p>In that case, we need to switch to B as the main chain and continue working from there.</p><p><img src="https://img.imzl.com/wp-content/uploads/2021/11/1637784118-bitcoin-mechanism-13.png" alt=""></p><p>Looking at the big picture, although different groups’ main chains may temporarily diverge at any given moment, the overall direction remains consistent. Those minor branches that occasionally sprout due to timing differences are quickly buried in history.</p><h3 id="What-if-miners-forge-the-ledger">What if miners forge the ledger?</h3><p>Satoshi explained that as long as the majority of the mining organization is honest, the system remains reliable. He addressed this from several angles.</p><p>First, thanks to the secret stamp mechanism, no one can forge someone else’s identity for payments, because the code generator checks all transaction slips’ stamps during ID generation and refuses to print if any stamp doesn’t match its stated payer.</p><p>Furthermore, honest miners will never approve illegitimate transactions (such as one where the payer has insufficient balance).</p><p>Therefore, the only possible attack vector is this: after the payee has confirmed receipt, the attacker creates an alternative transaction on a different branch, cancels the previous payment, and spends the same funds again to someone else (the so-called “double-spending” problem). Let’s illustrate with an example.</p><p>Suppose an attacker has 10 bitcoins and plans to pay this same amount to two victims, A and B, getting both transactions accepted.</p><p>Step one: The attacker plans to buy 10 bitcoins’ worth of gold from Victim A. He signs a transaction slip transferring 10 bitcoins to Victim A.</p><p><img src="https://img.imzl.com/wp-content/uploads/2021/11/1637784169-bitcoin-mechanism-14.png" alt=""></p><p>Step two: This transaction gets confirmed in the latest ledger page and is posted by the mining groups. Victim A sees the announcement, confirms the bitcoins have arrived, and gives the attacker gold worth 10 bitcoins.</p><p><img src="https://img.imzl.com/wp-content/uploads/2021/11/1637784229-bitcoin-mechanism-15.png" alt=""></p><p>Step three: The attacker goes back to the ledger page just before the one containing the transaction with Victim A and creates a new branch, generating enough pages to overtake the original branch. Since the attacker’s branch is now the main chain, the branch containing Victim A’s payment becomes a side branch. The mining organization no longer recognizes the earlier transfer, and Victim A’s 10 bitcoins are reversed.</p><p><img src="https://img.imzl.com/wp-content/uploads/2021/11/1637784270-bitcoin-mechanism-16.png" alt=""></p><p>Step four: The attacker can now sign another transaction slip, paying the same 10 bitcoins to Victim B. Once Victim B confirms receipt, they hand over gold of equivalent value.<br><img src="https://img.imzl.com/wp-content/uploads/2021/11/1637784303-bitcoin-mechanism-17.png" alt=""></p><p>At this point, the attacker has spent the same 10 bitcoins twice, purchasing equivalent gold from two victims. The attacker could repeat this trick — cancel the transaction with Victim B, and pay the same funds to yet another person…</p><p>To counter this attack, Satoshi’s recommended solution is that payees should not immediately confirm a transaction when it first appears on the bulletin board. Instead, they should wait and watch for the mining groups to post six more confirmation pages after the one containing their transaction, and only confirm receipt if the original page hasn’t been rolled back.</p><p>Satoshi explained that the fiendish ID rules were specifically designed to defend against this. As described earlier, generating a valid ledger page is no trivial matter — it requires massive effort trying different Lucky Numbers, and the process is entirely a matter of luck. If a ledger page containing your incoming payment has six more pages built on top of it, it becomes extremely difficult for an attacker to overtake the current main chain from a branch that’s six pages behind — unless the attacker commands more manpower than all the honest miners combined.</p><p>Moreover, if an attacker had that much manpower, it would be far more profitable to simply mine honestly than to waste such enormous resources on this kind of attack. This eliminates the motivation for attacks at a fundamental level.</p><h3 id="Won’t-bitcoins-keep-increasing-indefinitely-causing-severe-inflation">Won’t bitcoins keep increasing indefinitely, causing severe inflation?</h3><p>Satoshi said, “I’ve thought of this too. I forgot to mention earlier — the operating manual I gave to the mining organization specifies that initially, generating one ledger page earns a group 50 bitcoins. But every 210,000 pages, the reward halves. For example, after 210,000 pages, each new page earns 25 bitcoins; after 420,000 pages, 12.5 bitcoins; and so on. By the time the ledger reaches 6,930,000 pages, there will be no more rewards for generating new pages. At that point, the total supply of bitcoins will be approximately 21,000,000 — this is Bitcoin’s total supply cap, so it won’t increase indefinitely.”</p><h3 id="With-no-rewards-no-one-will-mine-and-there’ll-be-no-one-to-confirm-transactions">With no rewards, no one will mine, and there’ll be no one to confirm transactions</h3><p>By then, miners’ income will shift from mining rewards to transaction fees. For instance, when making a transfer, you can designate 1% as a transaction fee paid to the group that generates the ledger page. Groups will prioritize confirming transactions with higher fees.</p><h3 id="If-the-number-of-miners-keeps-growing-will-bitcoins-be-generated-faster">If the number of miners keeps growing, will bitcoins be generated faster?</h3><p>No. Satoshi explained that while anyone can freely join or leave the mining organization, causing the number of miners to fluctuate — and each miner does receive a code generator — he has already built a difficulty adjustment mechanism into the code generators. The more generators currently in operation, the lower each machine’s efficiency, ensuring the rate of new ledger page generation remains constant.</p><h3 id="Although-everyone-uses-pseudonyms-if-someone’s-pseudonym-is-leaked-and-the-ledger-is-public-couldn’t-all-their-transactions-be-traced">Although everyone uses pseudonyms, if someone’s pseudonym is leaked and the ledger is public, couldn’t all their transactions be traced?</h3><p>Indeed. For example, to transact with someone, you necessarily need their pseudonym to fill in the transaction slip’s payee field. However, Satoshi said he can provide an unlimited number of secret stamps, and he recommends using a different stamp for each transaction. This way, tracing the ledger won’t reveal all transactions belonging to a single person.</p><p>Q&amp;A complete.</p><h2 id="Notes">Notes</h2><p>This article uses accessible analogies to explain Bitcoin’s operating mechanism. A few things to note:</p><p>For the sake of clarity, I’ve made many simplifications, so some mechanistic details may not perfectly match the actual Bitcoin protocol. However, the overall philosophy and key principles are consistent.<br>Since many concepts from the computer world (such as public key cryptography and network transmission) don’t have perfect real-world equivalents, some parts of the story may feel a bit forced or unrealistic.<br>This article describes the technical principles and operating mechanism of the Bitcoin network itself. When trading Bitcoin on exchanges like Mt. Gox, the exchange acts as an intermediary and does not follow the mechanism described above.</p><h2 id="References">References</h2><ol><li><a href="https://bitcoin.org/bitcoin.pdf">Bitcoin Whitepaper (English)</a></li><li><a href="https://bitcoin.org/files/bitcoin-paper/bitcoin_zh_cn.pdf">Bitcoin Whitepaper (Chinese)</a></li><li><a href="https://bitcoin.it/">Bitcoin Wiki (English)</a></li><li><a href="https://blog.codingnow.com/2011/05/bitcoin.html">Cloud Wu’s Blog: “Basic Principles of Bitcoin”</a></li></ol><p>via. <a href="https://blog.codinglabs.org/articles/bitcoin-mechanism-make-easy.html">Original article</a></p>]]>
      </content:encoded>
    </item>
    <item>
      <title>What Is a Product Person?</title>
      <link>https://imzl.com/en/producter.html</link>
      <description>A reflection on what it means to be a product person: how product managers must balance business value and user value. Learn to look beyond surface-level design interactions and find the true competitive edge of a product.</description>
      <author>Len Chou</author>
      <category domain="https://imzl.com/en/categories/miscellanies/">Miscellanies</category>
      <category domain="https://imzl.com/en/categories/internet/">Internet</category>
      <category domain="https://imzl.com/en/categories/thinking/">Thinking</category>
      <category domain="https://imzl.com/en/tag/product-manager/">Product Manager</category>
      <pubDate>Mon, 06 Sep 2021 13:00:00 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>I’ve shared this on Twitter before, but I’m archiving it here on the blog as a reminder. This is something I’ve been practicing consistently.</p><p>A product person must first understand the balance between business value and user value — that is, what do we gain through the product, and what does the user gain? This is the innermost core of user experience. From there, you peel back the layers one by one. Unfortunately, most products on the market are fixated on the surface layer — the flashy, eye-catching design and interaction. I’ve always felt this is the lingering poison of the book “Everyone Is a Product Manager.”</p><p>A good product, beyond having a thorough grasp of the five layers of experience, must also have foresight. A big, comprehensive product is easy to copy, but at the cost of time — and your strategy, tactics, and resource allocation may not even be aligned. What’s truly impressive is your product sequencing: each move serves as the setup for the next. Simplicity doesn’t mean you haven’t thought things through — quite the opposite. See far, step close, think more, do less. Validate, then iterate fast.</p><p>And a truly outstanding product? It finds the critical mission within a red ocean and strikes with dimensional advantage.</p><p><img src="https://img.imzl.com/wp-content/uploads/2021/09/1630932266-dedao-chanping.jpeg" alt="Product Person"></p>]]>
      </content:encoded>
    </item>
    <item>
      <title>The Three Great Pleasures of Independent Blogging: Themes, Domains, and CMS Platforms</title>
      <link>https://imzl.com/en/theme-domain-blogcms.html</link>
      <description>Since 2010, I've been blogging for over a decade, having changed domains five times, themes over a dozen times, and CMS platforms twice. Perhaps because of my design background, I was overly fixated on the presentation layer — chasing aesthetics and perfection. With plenty of free time as a student, I poured enormous effort into themes, plugins, and server maintenance. Others might see this as a waste of time, but for me back then: the thrill of tinkering to satisfy my own needs and ideas could only be described as 'euphoria.'</description>
      <author>Len Chou</author>
      <category domain="https://imzl.com/en/categories/miscellanies/">Miscellanies</category>
      <category domain="https://imzl.com/en/tag/miscellanies/">Miscellanies</category>
      <category domain="https://imzl.com/en/tag/blog/">Blog</category>
      <category domain="https://imzl.com/en/tag/domain/">Domain</category>
      <pubDate>Wed, 25 Aug 2021 12:00:00 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>I recently acquired <a href="https://imzl.com">imzl.com</a>, fulfilling my “dream” of owning a decent-looking .com domain. It now serves as my blog’s primary domain, marking the third domain change for Zhou Liang’s Blog since 2020.</p><p>Since 2010, I’ve been blogging for over a decade<sup class="footnote-ref"><a href="#fn1" id="fnref1">[1]</a></sup>, having changed domains five times, themes over a dozen times, and CMS platforms twice<sup class="footnote-ref"><a href="#fn2" id="fnref2">[2]</a></sup>. Perhaps because of my design background<sup class="footnote-ref"><a href="#fn3" id="fnref3">[3]</a></sup>, I was overly fixated on the presentation layer — chasing aesthetics and perfection. With plenty of free time as a student, I poured enormous effort into themes, plugins, and server maintenance. Others might see this as a waste of time, but for me back then: <strong>the thrill of tinkering to satisfy my own needs and ideas could only be described as “euphoria.”</strong></p><p>This is why I say: independent blogging has three great pleasures — themes, domains, and CMS platforms. <strong>But pleasure is for yourself; value is for your readers.</strong></p><p>The value of a blog lies in its content — good, useful content.</p><p><strong>Blog Theme</strong>: Clean is enough. It should present content clearly and be easy to read — a bit rough around the edges is perfectly fine. A search box so readers can find what they’re looking for, and a comment box so you can converse with them — that’s all you need.</p><p><strong>Domain</strong>: Ideally short and memorable at a glance, but it’s no big deal if it isn’t. Domains carry less and less weight these days. The principle should be: use what you have, as long as it works. Don’t be like me, constantly switching. I only do it because of a personal hang-up, but it’s really not necessary. If the content is good enough, I’ll bookmark even the most ungainly domain.</p><p><strong>CMS Platform</strong>: As long as it works — the simpler, the better, even. Don’t let the tool limit you, and don’t make the startup cost of writing too high. These days I just finish writing in my notes app and paste-publish with one click, completely ignoring all those bells and whistles in the backend. The unformatted, plain-text approach to writing is simply wonderful.</p><p>This might sound a bit “utilitarian,” but as long as you’re comfortable, anything goes.</p><p>What I’m really doing here is a reflection — one I should have written four years ago. I used to be overly obsessed with surface-level flash (and this goes beyond blogging). Being a designer, there was nothing wrong with that per se. It wasn’t until I transitioned to product management that I realized beneath the dazzling surface lies something invisible. User experience isn’t just about the framework and presentation layers — dig deeper and you’ll find structure, scope, and strategy. It’s not enough to just make features look good and feel smooth. The balance between business value and user value — that’s the true core of experience.</p><p>When it comes to writing and blogging, the quality of your domain or the beauty of your theme are by no means prerequisites for a good blog. Strive for quality, but don’t obsess over perfection. Put your energy into the content — that’s what truly matters.</p><hr class="footnotes-sep"><section class="footnotes"><ol class="footnotes-list"><li id="fn1" class="footnote-item"><p>Started in middle school around 2010; updated frequently during school years, sporadically over the past 4 years. <a href="#fnref1" class="footnote-backref">↩︎</a></p></li><li id="fn2" class="footnote-item"><p>Switched from a self-hosted WordPress site to Bitcron, then back to WordPress. <a href="#fnref2" class="footnote-backref">↩︎</a></p></li><li id="fn3" class="footnote-item"><p>Previously worked as a UI designer. <a href="#fnref3" class="footnote-backref">↩︎</a></p></li></ol></section>]]>
      </content:encoded>
    </item>
    <item>
      <title>Oct 15, 2020 Notes: The Definition of Wealthy, iOS Workday Smart Alarm, iPhone 12</title>
      <link>https://imzl.com/en/857.html</link>
      <description>Distinguishing between 'truly wealthy' and 'pretending to be wealthy' is important. At minimum, one should meet these two criteria to be considered 'wealthy,' as Andrew Hallam also argues: 1. Being able to choose not to work without worrying about making ends meet; 2. Holding investments that guarantee lifetime earnings at twice the national median household income. (In 2020, Shanghai's median household annual income was 240,000-600,000 RMB.)</description>
      <author>Len Chou</author>
      <category domain="https://imzl.com/en/categories/miscellanies/">Miscellanies</category>
      <category domain="https://imzl.com/en/tag/riches/">Wealth</category>
      <category domain="https://imzl.com/en/tag/iPhone/">iPhone</category>
      <pubDate>Thu, 15 Oct 2020 14:00:00 GMT</pubDate>
      <content:encoded>
        <![CDATA[<h2 id="What-Does-It-Mean-to-Be-Wealthy">What Does It Mean to Be Wealthy?</h2><p>Distinguishing between “truly wealthy” and “pretending to be wealthy” is important. At minimum, one should meet the following two criteria to be considered “wealthy” — Andrew Hallam shares this view:</p><ol><li>Being able to choose not to work without worrying about making ends meet.</li><li>Holding investments that guarantee lifetime earnings at twice the national median household income. (In 2020, Shanghai’s median household annual income was 240,000-600,000 RMB.)</li></ol><h2 id="iOS-Workday-Smart-Alarm">iOS Workday Smart Alarm</h2><p>iOS alarms have never supported automatic on/off based on China’s official public holidays. Today I came across a fully automated solution via Shortcuts on @scomper’s blog. It works by subscribing to a Chinese public holiday calendar combined with Shortcuts, or through an online API plus Shortcuts processing.</p><p>Full tutorial here: <a href="https://pepcn.com/ios/iosshang-de-gong-zuo-nao-zhong">iOS Workday Alarm Clock</a></p><h2 id="iPhone-12">iPhone 12</h2><p>The iPhone 12 is finally here — pre-orders open at 8 PM tomorrow. I’ve been using my iPhone 7 for four years, so it’s finally time for an upgrade. This time I won’t be buying through the official Apple Store. I’ll look into supplier channels or Pinduoduo instead — the price difference should be enough to cover installment fees.</p><h2 id="Resume">Resume</h2><p>I’ve been helping Teacher Wu revise his resume recently, which has also sparked the idea of updating my own. My past few job switches didn’t require a resume, so the current version still reflects my time as a designer. I can set aside some time this weekend to put together a product-focused resume and take stock of my years in product management along the way.</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>The World of Cultivation</title>
      <link>https://imzl.com/en/868.html</link>
      <description>Exploring the striking parallels between the 'cultivation world' of Chinese fantasy fiction and real-world professional life. From spiritual energy to alchemy, how principles from Xianxia cultivation can be mapped onto your professional skills and talents.</description>
      <author>Len Chou</author>
      <category domain="https://imzl.com/en/categories/miscellanies/">Miscellanies</category>
      <category domain="https://imzl.com/en/categories/thinking/">Thinking</category>
      <category domain="https://imzl.com/en/tag/imagination/">Imagination</category>
      <category domain="https://imzl.com/en/tag/function/">Function</category>
      <category domain="https://imzl.com/en/tag/cultivation-fantasy/">Cultivation Fantasy</category>
      <pubDate>Thu, 24 Sep 2020 14:00:00 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>I once pondered a question: isn’t chemistry essentially “alchemy,” and isn’t physics essentially “the laws of the Dao”? If our textbooks had been renamed accordingly, perhaps I would have been far more motivated to study back in the day.</p><p>Last night while taking a shower, it struck me again. In the world of Xianxia (cultivation fantasy) novels, there are all kinds of cultivation methods. Cultivating spiritual energy internally, tempering the body externally, refining pills with one hand and forging artifacts with the other. Isn’t this exactly analogous to the various professional roles in my work — product management, operations, business development, and so on?</p><p>And the geniuses of the cultivation world? Perhaps they are the ones who can both venture outward and cultivate their inner strength.</p><p>Some people possess formidable spiritual power. Others combine that spiritual power with being a rare pill-refining master. The more disciplines one masters, the higher one’s “cultivation talent and realm.” And in this system, cultivation talent and realm refer more to diligence, serendipity, the passage of time, and the insights gained from life-or-death battles.</p><p>Indeed, all paths lead to the same destination.</p><p>Seen in this light, this infinite game grows ever more fascinating — ever more “gamified.”</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>Automatically Insert Custom Classes into a, p, and Other Tags in WordPress Post Content</title>
      <link>https://imzl.com/en/wordpress-content-insert-class.html</link>
      <description>How to automatically insert specified CSS classes into a, p, and other HTML tags within WordPress post content.</description>
      <author>Len Chou</author>
      <category domain="https://imzl.com/en/categories/wordpress/">WordPress</category>
      <category domain="https://imzl.com/en/tag/wordpress-tutorial/">WordPress Tutorial</category>
      <category domain="https://imzl.com/en/tag/wordpress-skill/">WordPress Tips</category>
      <pubDate>Fri, 31 Jul 2020 15:10:00 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>Last week I was building a theme that incorporated an open-source CSS framework. Adding classes to various front-end elements was straightforward enough. But when it came to post content, things got tricky — the content is output by WordPress itself, so I had no control over the classes being used.</p><p>I asked @desin (the author of the “I Love Boiled Fish” blog) if there was a way to add classes without writing JavaScript. He suggested I look into the content filter documentation. After some research, the problem was solved.</p><p>Here’s the code — feel free to use it as reference. Copy the following and paste it right below the <code>&lt;?php</code> line in your theme’s <code>functions.php</code> file:</p><pre><code class="highlight php"><span class="comment"># Automatically add img-res class to img tags in post content</span><span class="function"><span class="keyword">function</span> <span class="title">img_paragraph</span>(<span class="params"><span class="variable">$content</span></span>)</span>&#123;    <span class="keyword">return</span> <span class="title function_ invoke__">preg_replace</span>(<span class="string">&#x27;/&lt;img([^&gt;]+)?&gt;/&#x27;</span>, <span class="string">&#x27;&lt;img$1 class=&quot;img-res&quot;&gt;&#x27;</span>, <span class="variable">$content</span>);&#125;<span class="title function_ invoke__">add_filter</span>(<span class="string">&#x27;the_content&#x27;</span>, <span class="string">&#x27;img_paragraph&#x27;</span>);</code></pre><p>Similarly, if you want to target p tags, the code would be:</p><pre><code class="highlight php"><span class="comment"># Automatically add mt1em, mb1em, and lh-180 classes to p tags in post content</span><span class="function"><span class="keyword">function</span> <span class="title">p_paragraph</span>(<span class="params"><span class="variable">$content</span></span>)</span>&#123;    <span class="keyword">return</span> <span class="title function_ invoke__">preg_replace</span>(<span class="string">&#x27;/&lt;p([^&gt;]+)?&gt;/&#x27;</span>, <span class="string">&#x27;&lt;p$1 class=&quot;mt1em mb1em lh-180&quot;&gt;&#x27;</span>, <span class="variable">$content</span>);&#125;<span class="title function_ invoke__">add_filter</span>(<span class="string">&#x27;the_content&#x27;</span>, <span class="string">&#x27;p_paragraph&#x27;</span>);</code></pre>]]>
      </content:encoded>
    </item>
    <item>
      <title>Fixing WordPress Stuck on &quot;Briefly Unavailable for Scheduled Maintenance&quot;</title>
      <link>https://imzl.com/en/wordpress-scheduled-maintenance.html</link>
      <description>It turns out that when WordPress upgrades its core, themes, or plugins, it switches to maintenance mode. During this time, visiting the front end displays &quot;Briefly unavailable for scheduled maintenance. Check back in a minute.&quot; If the upgrade goes smoothly, it returns to normal within seconds. However, poor network conditions or other issues can cause the upgrade to stall, leaving WordPress permanently stuck in maintenance mode — both front end and back end showing &quot;Briefly unavailable for scheduled maintenance. Check back in a minute.&quot;</description>
      <author>Len Chou</author>
      <category domain="https://imzl.com/en/categories/wordpress/">WordPress</category>
      <category domain="https://imzl.com/en/tag/wordpress-tutorial/">WordPress Tutorial</category>
      <category domain="https://imzl.com/en/tag/wordpress-skill/">WordPress Tips</category>
      <pubDate>Fri, 31 Jul 2020 14:54:00 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>Today while upgrading a plugin on my personal blog, I ran into an issue: both the front end and back end were stuck on a blank page displaying “Briefly unavailable for scheduled maintenance. Check back in a minute.” I was completely baffled.</p><p>It turns out that when WordPress upgrades its core, themes, or plugins, it switches to maintenance mode. During this time, visiting the front end displays “Briefly unavailable for scheduled maintenance. Check back in a minute.” If the upgrade goes smoothly, it returns to normal within seconds. However, poor network conditions or other issues can cause the upgrade to stall, leaving WordPress permanently stuck in maintenance mode — both front end and back end showing “Briefly unavailable for scheduled maintenance. Check back in a minute.”</p><h2 id="How-to-Fix-This">How to Fix This</h2><p>Delete the <code>.maintenance</code> file in your website’s root directory.</p><p><code>.maintenance</code> is a hidden file that typically won’t show up when browsing via FTP. I recommend using SSH instead. Follow these steps:</p><ol><li><code>cd /home/xxx/xxx</code> — navigate to the root directory of the affected WordPress site.</li><li><code>ls -a</code> — list all files in the current directory, including hidden ones. Check if <code>.maintenance</code> exists; if so, proceed to delete it.</li><li><code>rm -rf .maintenance</code> — press Enter to delete. Problem solved.</li></ol>]]>
      </content:encoded>
    </item>
    <item>
      <title>The Perfect 301 Redirect Solution After Changing Your WordPress Domain</title>
      <link>https://imzl.com/en/wordpress-301.html</link>
      <description>
        <![CDATA[<p>I recently changed the domain for my <a href="https://imzl.com" title="personal blog">personal blog</a>. After the switch, I needed to se]]>
      </description>
      <author>Len Chou</author>
      <category domain="https://imzl.com/en/categories/wordpress/">WordPress</category>
      <category domain="https://imzl.com/en/tag/wordpress-tutorial/">WordPress Tutorial</category>
      <category domain="https://imzl.com/en/tag/wordpress-skill/">WordPress Tips</category>
      <pubDate>Fri, 24 Jul 2020 08:26:00 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>I recently changed the domain for my <a href="https://imzl.com" title="personal blog">personal blog</a>. After the switch, I needed to set up 301 redirects from the old domain to the new one — for example, visiting <a href="https://imzl.com">https://zlbk.net</a> (old domain) should automatically redirect to <a href="https://imzl.com">https://imzl.com</a> (new domain), seamlessly.</p><p>This not only improves the visitor experience but also transfers domain authority and search engine indexing. This article documents the methods for implementing 301 redirects.</p><h2 id="Using-WordPress-to-Implement-URL-Specific-301-Redirects">Using WordPress to Implement URL-Specific 301 Redirects</h2><ol><li>Please note: this method requires keeping the original WordPress files on the old domain. If you’ve already run a SQL find-and-replace on the domain in the original codebase and the old domain no longer has a separate WordPress installation, this method won’t work.</li><li>Locate the <code>wp-blog-header.php</code> file in your WordPress root directory and add the following code below the first <code>&lt;?php</code> line:</li></ol><pre><code class="highlight php"><span class="comment">// WordPress domain change 301 redirect</span><span class="comment">// Replace imzl.com with your new domain</span><span class="keyword">if</span> (<span class="title function_ invoke__">strtolower</span>(<span class="variable">$_SERVER</span>[<span class="string">&#x27;SERVER_NAME&#x27;</span>])!=<span class="string">&#x27;imzl.com&#x27;</span>)&#123;<span class="variable">$URIRedirect</span>=<span class="variable">$_SERVER</span>[<span class="string">&#x27;REQUEST_URI&#x27;</span>];<span class="keyword">if</span>(<span class="title function_ invoke__">strtolower</span>(<span class="variable">$URIRedirect</span>)==<span class="string">&quot;/index.php&quot;</span>)&#123;<span class="variable">$URIRedirect</span>=<span class="string">&quot;/&quot;</span>;&#125;<span class="title function_ invoke__">header</span>(<span class="string">&#x27;HTTP/1.1 301 Moved Permanently&#x27;</span>);<span class="title function_ invoke__">header</span>(<span class="string">&#x27;Location:https://imzl.com&#x27;</span>.<span class="variable">$URIRedirect</span>);<span class="keyword">exit</span>();&#125;</code></pre><ol start="3"><li>Replace the corresponding file on your server. Done.</li></ol><h2 id="Using-Nginx-to-Implement-URL-Specific-301-Redirects">Using Nginx to Implement URL-Specific 301 Redirects</h2><p>This method does not require keeping the WordPress codebase.</p><ol><li>Locate your Nginx configuration file and add the following code below the <code>server_name</code> directive:</li></ol><pre><code class="highlight plaintext">// Replace imzl.com with your new site&#x27;s domainreturn 301 https://imzl.com$request_uri;</code></pre><ol start="2"><li>Upload the modified Nginx configuration file and restart Nginx via terminal using the <code>service nginx restart</code> command.</li></ol>]]>
      </content:encoded>
    </item>
    <item>
      <title>The Kids Who Chased Balloons</title>
      <link>https://imzl.com/en/166.html</link>
      <description>&quot;The Kids Who Chased Balloons&quot; exposes how Youku and Momo mistreated a young creator named Niko. Backed by authentic emails, recordings, and video evidence, the article has garnered over 100,000 shares. Dive into this true story that rocked the Chinese internet and the hidden business ethics issues behind it.</description>
      <author>Len Chou</author>
      <category domain="https://imzl.com/en/categories/miscellanies/">Miscellanies</category>
      <category domain="https://imzl.com/en/categories/internet/">Internet</category>
      <category domain="https://imzl.com/en/tag/youku/">Youku</category>
      <category domain="https://imzl.com/en/tag/momo/">Momo</category>
      <pubDate>Mon, 02 Apr 2018 06:23:00 GMT</pubDate>
      <content:encoded>
        <![CDATA[<!-- ![171000475.jpeg](ipfs://bafkreibgzsevyojkwcigdfjd4taro77ovooyfjam3pexfvdqm6gpanzily) --><p>These past few days, my WeChat Moments feed has been flooded again. The story that went viral was written by a young man named Niko, titled “Youth Shall Not Be Bullied,” calling out Youku and Momo. The gist is that Niko and a few friends planned an event to “photograph the Earth from a weather balloon” — and they pulled it off. Afterward, an editor surnamed Wang from Youku contacted Niko to discuss a collaboration. After learning the full details of the kids’ planning and execution, this editor shelved the shoot under various pretexts, then went ahead and had someone else produce a creative short film based on the same concept.</p><p>Niko provided emails, audio recordings, and video evidence to support his accusations. The story largely checks out with Niko’s account. The article has been shared over 100,000 times, sparking a massive wave of public outrage against Youku and Momo.</p><p>Judging the matter on its own merits, the editor surnamed Wang at Youku deserves condemnation. Using “collaboration” as a pretext, he gained the kids’ trust, extracted key information, then kicked them to the curb. Sound familiar? You may have encountered variations of this playbook: a company planning a redesign invites several design agencies to bid, listens to all their creative pitches, then cancels the bidding process under various excuses — only to base their redesign on those agencies’ proposals. Or a VC invests in one product, then meets with several of its competitors, extracts their strategies, and feeds them to the team they’ve already funded…</p><p>Behind all of this lies a single mentality: stealing ideas doesn’t count as stealing — it’s not even a thing. I’ve been through this a few times myself. I wanted to build a product, and the other party also wanted to build something similar. They claimed they wanted to bring me on board, talked with me extensively to understand my ideas, then booted me out with the excuse that I wasn’t a good fit for their team. The resulting product was riddled with my original ideas. Fortunately, it ended up being lukewarm — otherwise I might have stepped forward to brag about it and gotten my fifteen minutes of fame too.</p><p>I can’t guarantee that “The Kids Who Chased Balloons” isn’t a publicity stunt. In an internet awash with manufactured controversies, any topic inevitably carries a whiff of hype. Niko clearly came out of this incident with substantial gains — perhaps even more exposure than a smooth collaboration with Youku would have brought. After all, people who sympathize with the underdog and consider themselves righteous still make up the majority. As for Momo, who appeared to be an innocent bystander, they too seem to have benefited enormously — without spending a dime, they got another massive wave of shares and comments (exposure), and even harvested sympathy through their PR response. Youku, sitting at the center of the storm, could have also come out as a winner if they’d handled things properly — but alas… well.</p><p>As for the truth of the matter, outsiders can only speculate. Only those directly involved will ever truly know.</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>WordPress Tips: Customizing the Maximum Upload File Size</title>
      <link>https://imzl.com/en/wordpress-maximum-upload-file-size.html</link>
      <description>By default, WordPress or your hosting provider controls the maximum upload file size. If you try to upload a file exceeding the preset limit, the upload will fail. This article explains several ways to customize the upload file size limit.</description>
      <author>Len Chou</author>
      <category domain="https://imzl.com/en/categories/wordpress/">WordPress</category>
      <category domain="https://imzl.com/en/tag/wordpress-tutorial/">WordPress Tutorial</category>
      <category domain="https://imzl.com/en/tag/wordpress-skill/">WordPress Tips</category>
      <pubDate>Thu, 22 Feb 2018 14:19:00 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p><img src="https://cdn.imzl.com/wp-content/uploads/2018/03/wordpress-maximum-upload-file-size-1.jpg" alt="Customizing WordPress Upload File Size"></p><p>By default, WordPress or your hosting provider controls the maximum upload file size. If you try to upload a file exceeding the preset limit, the upload will fail. This article explains several ways to customize the upload file size limit.</p><h2 id="Check-the-Default-WordPress-Upload-File-Size">Check the Default WordPress Upload File Size</h2><p>Navigate to “Media - Add New” in the dashboard menu. On this page, you’ll find your site’s current default upload size limit. As shown in the screenshot below, my WordPress site has a default upload limit of 10MB. In this article, I’ll demonstrate several methods to change this limit to 20MB — feel free to set your own value.<br><img src="https://cdn.imzl.com/wp-content/uploads/2018/03/wordpress-maximum-upload-file-size-2.png" alt="Check the Default WordPress Upload File Size" title="Check the Default WordPress Upload File Size"></p><h2 id="Contact-Your-Hosting-Provider">Contact Your Hosting Provider</h2><p>If you’re using a managed WordPress hosting platform, these platforms typically offer a default option to customize the file upload size limit (in most cases, the settings page can be found in your server management dashboard).</p><p>Take Cloudways as an example: after logging in, navigate to the “Settings &amp; Packages” page from the menu. In the UPLOAD SIZE field, enter your desired maximum upload file size and click Save. <img src="https://cdn.imzl.com/wp-content/uploads/2018/03/wordpress-maximum-upload-file-size-3.png" alt="Setting WordPress Maximum Upload Size in Cloudways Dashboard" title="Setting WordPress Maximum Upload Size in Cloudways Dashboard"></p><h2 id="Modify-or-Create-a-php-ini-File">Modify or Create a php.ini File</h2><p>php.ini is a configuration file located in the root directory. Some providers may name it “php5.ini.” It contains a series of settings including maximum upload file size, maximum execution time, upload directory, global variable controls, and more.</p><p>For security reasons, most hosting providers keep it hidden. To find this file, you’ll need to access the server’s root directory and may need to show hidden files. If you still can’t find it, create one yourself — just make sure the configuration it contains is correct. If you’re unsure what configuration values to include, a quick search will turn up plenty of detailed guides.</p><p>To set the maximum upload size to 20MB, we need to change <code>upload_max_filesize</code> to 20 and <code>post_max_size</code> to around 25MB.</p><pre><code class="highlight php">upload_max_filesize = <span class="number">20</span>Mpost_max_size = <span class="number">25</span>Mmemory_limit = <span class="number">30</span>M</code></pre><p>Note: “M” stands for “MB.” <code>memory_limit</code> should be equal to or greater than <code>upload_max_filesize</code> — to be safe, I’ve set it to 30MB.</p><h2 id="Modify-Create-an-htaccess-File">Modify/Create an .htaccess File</h2><p>.htaccess stands for “distributed configuration file.” It’s a configuration file used by the Apache server. It’s typically located in the root directory and may be hidden — you can find it by enabling the display of hidden files.</p><p>If you locate this file, simply copy and paste the following code to achieve our goal:</p><pre><code class="highlight php">php_value upload_max_filesize <span class="number">20</span>MBphp_value post_max_size <span class="number">25</span>MBphp_value memory_limit <span class="number">30</span>MB</code></pre><h2 id="Modify-WordPress-Configuration">Modify WordPress Configuration</h2><p>The three methods above are what I consider the most reliable approaches. If none of them work, you can try pasting the following code into WordPress’s <code>wp-config.php</code> or your active theme’s <code>functions.php</code>:</p><pre><code class="highlight php">@<span class="title function_ invoke__">ini_set</span>( <span class="string">&#x27;upload_max_size&#x27;</span> , <span class="string">&#x27;20MB&#x27;</span> );@<span class="title function_ invoke__">ini_set</span>( <span class="string">&#x27;post_max_size&#x27;</span>, <span class="string">&#x27;25MB&#x27;</span>);@<span class="title function_ invoke__">ini_set</span>( <span class="string">&#x27;memory_limit&#x27;</span>, <span class="string">&#x27;30MB&#x27;</span> );</code></pre><h2 id="Control-Upload-Size-via-a-WordPress-Plugin">Control Upload Size via a WordPress Plugin</h2><p>One of the main reasons I love WordPress is its comprehensive ecosystem, with countless plugins that can solve virtually any problem. If you’d rather skip the manual configuration, I recommend a plugin called “<a href="https://wordpress.org/plugins/upload-max-file-size/">Increase Max Upload Filesize</a>.”</p><p>Search for and install it from the backend plugin directory. Once installed, go to its settings page and enter the desired size limit in bytes (1,024,000 bytes = 1 MB). If, like me, you want to set it to 20MB, simply enter 20480000 and click Save. <img src="https://cdn.imzl.com/wp-content/uploads/2018/03/wordpress-maximum-upload-file-size-4.png" alt="Controlling Upload File Size via the Increase Max Upload Filesize WordPress Plugin" title="Controlling Upload File Size via the Increase Max Upload Filesize WordPress Plugin"></p><h2 id="Still-Haven’t-Solved-Your-Problem">Still Haven’t Solved Your Problem?</h2><p>If none of the five methods listed above resolved your issue, it’s simple — you can leave a comment and let me know, or reach out to your hosting provider via support tickets or email. They should be able to help.</p><p>If you’re the sole user of your WordPress site, you can always upload files via FTP to <code>/wp-content/uploads/</code>, then use the <a href="https://wordpress.org/plugins/media-from-ftp/">Media from FTP</a> plugin to make those FTP-uploaded files appear in your media library.</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>Exclude Specific Posts, Pages, and Categories from WordPress Search Results, or Show Only Specific Categories</title>
      <link>https://imzl.com/en/wordpress-search-filter-pges-post-classify.html</link>
      <description>By default, WordPress search results include pages, posts, and more. While reorganizing my blog, I needed to control what appears in search results and exclude content I don't want readers to find.</description>
      <author>Len Chou</author>
      <category domain="https://imzl.com/en/categories/wordpress/">WordPress</category>
      <category domain="https://imzl.com/en/tag/wordpress-tutorial/">WordPress Tutorial</category>
      <category domain="https://imzl.com/en/tag/wordpress-skill/">WordPress Tips</category>
      <pubDate>Fri, 27 Oct 2017 04:43:00 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>By default, the WordPress search mechanism returns results that include all pages, posts, and other content types on the site. While reorganizing Zhou Liang’s Blog recently, I needed to gain some control over what appears in search results and exclude content I don’t want readers to find.</p><p>From an efficiency standpoint, I’m not a fan of reinventing the wheel, so I searched for some existing code snippets. This post is purely a memo for myself.</p><h2 id="Exclude-Specific-Posts-or-Pages-by-ID">Exclude Specific Posts or Pages by ID</h2><pre><code class="highlight php"><span class="comment">//Exclude specific posts or pages by ID from search results</span><span class="function"><span class="keyword">function</span> <span class="title">Bing_search_filter_id</span>(<span class="params"><span class="variable">$query</span></span>) </span>&#123;<span class="keyword">if</span> ( !<span class="variable">$query</span>-&gt;is_admin &amp;&amp; <span class="variable">$query</span>-&gt;is_search) &#123;<span class="variable">$query</span>-&gt;<span class="title function_ invoke__">set</span>(<span class="string">&#x27;post__not_in&#x27;</span>, <span class="keyword">array</span>(<span class="number">13</span>,<span class="number">14</span>));<span class="comment">//IDs of posts/pages to exclude</span>&#125;<span class="keyword">return</span> <span class="variable">$query</span>;&#125;<span class="title function_ invoke__">add_filter</span>(<span class="string">&#x27;pre_get_posts&#x27;</span>,<span class="string">&#x27;Bing_search_filter_id&#x27;</span>);</code></pre><h2 id="Exclude-All-Posts-Under-Specific-Categories">Exclude All Posts Under Specific Categories</h2><pre><code class="highlight php"><span class="comment">//Exclude all posts under specific categories from search results</span><span class="function"><span class="keyword">function</span> <span class="title">Bing_search_filter_category</span>(<span class="params"> <span class="variable">$query</span></span>) </span>&#123;<span class="keyword">if</span> ( !<span class="variable">$query</span>-&gt;is_admin &amp;&amp; <span class="variable">$query</span>-&gt;is_search) &#123;<span class="variable">$query</span>-&gt;<span class="title function_ invoke__">set</span>(<span class="string">&#x27;cat&#x27;</span>,<span class="string">&#x27;-11,-13&#x27;</span>); <span class="comment">//Category IDs; prefix with minus sign to exclude; without the minus sign, search is limited to that category</span>&#125;<span class="keyword">return</span> <span class="variable">$query</span>;&#125;<span class="title function_ invoke__">add_filter</span>(<span class="string">&#x27;pre_get_posts&#x27;</span>,<span class="string">&#x27;Bing_search_filter_category&#x27;</span>);</code></pre><h2 id="Exclude-All-Pages-from-Search-Results">Exclude All Pages from Search Results</h2><pre><code class="highlight php"><span class="comment">//Exclude all pages from search results</span><span class="function"><span class="keyword">function</span> <span class="title">search_filter_page</span>(<span class="params"><span class="variable">$query</span></span>) </span>&#123;<span class="keyword">if</span> (<span class="variable">$query</span>-&gt;is_search) &#123;<span class="variable">$query</span>-&gt;<span class="title function_ invoke__">set</span>(<span class="string">&#x27;post_type&#x27;</span>, <span class="string">&#x27;post&#x27;</span>);&#125;<span class="keyword">return</span> <span class="variable">$query</span>;&#125;<span class="title function_ invoke__">add_filter</span>(<span class="string">&#x27;pre_get_posts&#x27;</span>,<span class="string">&#x27;search_filter_page&#x27;</span>);</code></pre>]]>
      </content:encoded>
    </item>
    <item>
      <title>WordPress Tips: Disabling Character Conversion</title>
      <link>https://imzl.com/en/wordpress-prohibits-character-conversion.html</link>
      <description>The WordPress editor automatically converts certain input characters by default — for example, code gets escaped into encoded entities, and quotation marks undergo full-width/half-width conversion. This article shows you the simplest way to disable character conversion.</description>
      <author>Len Chou</author>
      <category domain="https://imzl.com/en/categories/wordpress/">WordPress</category>
      <category domain="https://imzl.com/en/tag/wordpress-tutorial/">WordPress Tutorial</category>
      <category domain="https://imzl.com/en/tag/wordpress-skill/">WordPress Tips</category>
      <pubDate>Fri, 20 Oct 2017 02:29:00 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>The WordPress editor automatically converts certain input characters by default — for example, code gets escaped into encoded entities, and quotation marks undergo full-width/half-width conversion.</p><p>This feature is quite unfriendly for my use case. When I enter code in the editor, what gets displayed isn’t the original code, and readers who copy it are in for a bad time. If your blog, like mine, doesn’t really need this feature, you might as well disable WordPress’s full-width/half-width character conversion altogether.</p><p>Add the following code to your current theme’s <code>functions.php</code> file:</p><pre><code class="highlight php"><span class="comment">//Disable content conversion</span><span class="title function_ invoke__">remove_filter</span>(<span class="string">&#x27;the_content&#x27;</span>, <span class="string">&#x27;wptexturize&#x27;</span>);<span class="comment">//Disable excerpt conversion</span><span class="title function_ invoke__">remove_filter</span>(<span class="string">&#x27;the_excerpt&#x27;</span>, <span class="string">&#x27;wptexturize&#x27;</span>);<span class="comment">//Disable comment conversion</span><span class="title function_ invoke__">remove_filter</span>(<span class="string">&#x27;comment_text&#x27;</span>, <span class="string">&#x27;wptexturize&#x27;</span>);</code></pre><p>Done. If you, like me, prefer writing in a plain-text environment, you can also combine this with the method described in “<a href="https://www.aips.me/change-the-wordpress-editor-default-view-to-html.html">Change the WordPress Editor Default View to HTML/Text</a>” to make the WordPress editor default to the non-visual text editor with character conversion disabled.</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>Change the WordPress Editor Default View to HTML/Text</title>
      <link>https://imzl.com/en/change-the-wordpress-editor-default-view-to-html.html</link>
      <description>This article will help you change the default WordPress editor view to HTML or plain text.</description>
      <author>Len Chou</author>
      <category domain="https://imzl.com/en/categories/wordpress/">WordPress</category>
      <category domain="https://imzl.com/en/tag/wordpress-tutorial/">WordPress Tutorial</category>
      <category domain="https://imzl.com/en/tag/wordpress-skill/">WordPress Tips</category>
      <pubDate>Thu, 19 Oct 2017 12:36:00 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>By default, the WordPress backend editor opens in the “Visual” view when editing posts, pages, and so on. At this point, I’ve essentially moved my entire writing workflow to plain-text Markdown with no formatting.</p><p>Every time I head to the WordPress backend to publish an article, I have to click “Text” first before I can paste in my content. It’s just too tedious.</p><p>So, as per the usual routine, let’s tweak the WordPress default settings and switch the editor’s default view to “HTML/Text.”</p><p>Add the following to your current WordPress theme’s <code>functions.php</code>:</p><pre><code class="highlight php"><span class="title function_ invoke__">add_filter</span>(<span class="string">&#x27;wp_default_editor&#x27;</span>, <span class="title function_ invoke__">create_function</span>(<span class="string">&#x27;&#x27;</span>, <span class="string">&#x27;return &quot;html&quot;;&#x27;</span>));</code></pre><p>And that’s it — done.</p>]]>
      </content:encoded>
    </item>
    <item>
      <title>Fixing WordPress Dashboard Showing Only One Theme Under LNMP</title>
      <link>https://imzl.com/en/lnmp-to-solve-the-wordpress-background-only-show-a-subject-problem.html</link>
      <description>The reason WordPress fails to recognize themes: the server environment has disabled the scandir function, preventing WordPress from properly caching themes. This article provides a definitive solution.</description>
      <author>Len Chou</author>
      <category domain="https://imzl.com/en/categories/wordpress/">WordPress</category>
      <category domain="https://imzl.com/en/tag/wordpress-tutorial/">WordPress Tutorial</category>
      <category domain="https://imzl.com/en/tag/wordpress-skill/">WordPress Tips</category>
      <category domain="https://imzl.com/en/tag/lnmp/">LNMP</category>
      <pubDate>Thu, 15 Jun 2017 01:22:00 GMT</pubDate>
      <content:encoded>
        <![CDATA[<p>The reason WordPress fails to recognize themes is that the server environment has disabled the <code>scandir</code> function, preventing WordPress from properly caching themes.</p><h2 id="How-to-fix-the-theme-recognition-issue-under-LNMP">How to fix the theme recognition issue under LNMP:</h2><ol><li>Locate <code>php.ini</code> — it’s typically found in the <code>/usr/local/php/etc</code> directory on the server.</li><li>Open <code>php.ini</code>, search for “<code>disable_functions</code>”, find and remove “<code>scandir</code>” from the list that follows, then save the file.</li><li>Restart the PHP service on your server for the changes to take effect.</li></ol>]]>
      </content:encoded>
    </item>
  </channel>
</rss>
