<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: 张桂雄</title>
    <description>The latest articles on Forem by 张桂雄 (@zhangguime).</description>
    <link>https://forem.com/zhangguime</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3857772%2Fbcb9cdeb-c58c-4f68-89ef-4aea20a88d25.png</url>
      <title>Forem: 张桂雄</title>
      <link>https://forem.com/zhangguime</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/zhangguime"/>
    <language>en</language>
    <item>
      <title>From Product Manager to Indie Hacker: A 0-to-1 Survival Guide for Launching My Overseas Tool Website</title>
      <dc:creator>张桂雄</dc:creator>
      <pubDate>Thu, 02 Apr 2026 14:12:17 +0000</pubDate>
      <link>https://forem.com/zhangguime/from-product-manager-to-indie-hacker-a-0-to-1-survival-guide-for-launching-my-overseas-tool-website-45da</link>
      <guid>https://forem.com/zhangguime/from-product-manager-to-indie-hacker-a-0-to-1-survival-guide-for-launching-my-overseas-tool-website-45da</guid>
      <description>&lt;p&gt;Hi everyone, I'm a product manager. Recently, I took on a hardcore side project: independently developing and launching a pure, ad-free online web tool suite — &lt;strong&gt;Web Tools Hub&lt;/strong&gt; (&lt;a href="https://web-tools.tech/" rel="noopener noreferrer"&gt;web-tools.tech&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The website has successfully run through the full-stack pipeline and is now indexed by Google. But the journey of pushing this project from my local machine to a production environment was paved with technical traps that nearly blew up my server. Today, I want to do a post-mortem and share why I built this site, as well as how I solved the bizarre DevOps headaches of deploying a Next.js app on a Baota (aaPanel) server.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Why build this web tool?
&lt;/h2&gt;

&lt;p&gt;As a PM, I deal with various digital assets daily and frequently rely on mini-tools for image cropping, color inversion, format conversion, etc. However, most tool websites on the market share the same frustrating pain points:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Ad Minefields:&lt;/strong&gt; You have to dodge three fake "Download" buttons just to find the real one.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Forced Logins:&lt;/strong&gt; They force you to register an account or scan a QR code just to use a basic feature once.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Privacy Risks:&lt;/strong&gt; Many tools that could easily run locally in the browser force you to upload your files to unknown servers.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Driven by the hacker ethos of "building is better than buying," I decided to create a clean, lightweight, multi-lingual tool site myself. No flashy pop-ups, no tracking nonsense. Just a core philosophy: &lt;strong&gt;Ready to use, and leave when you're done.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. The "Technical Pits" of Development and SEO
&lt;/h2&gt;

&lt;p&gt;For the tech stack, I chose the highly popular &lt;strong&gt;Next.js&lt;/strong&gt;. The developer experience was phenomenal, but when optimizing for SEO, I got completely stuck on a tiny &lt;code&gt;sitemap.xml&lt;/code&gt; issue.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pitfall Record: Sitemap formatting and i18n adaptation&lt;/strong&gt;&lt;br&gt;
To target an overseas audience, my site supports multi-language routing (i18n) for English, Spanish, Portuguese, etc. Initially, the Sitemap I generated kept throwing errors in the Google Search Console (GSC).&lt;/p&gt;

&lt;p&gt;After diving deep into the documentation, I realized a standard Sitemap must use &lt;code&gt;&amp;lt;urlset&amp;gt;&lt;/code&gt; as the root wrapper element, not &lt;code&gt;&amp;lt;sitemapindex&amp;gt;&lt;/code&gt;. By dynamically generating URLs for all multi-language subpages within Next.js's &lt;code&gt;app/sitemap.ts&lt;/code&gt;, and ensuring they were tagged with &lt;code&gt;&amp;lt;lastmod&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;changefreq&amp;gt;&lt;/code&gt;, the Google bot finally recognized my 30+ pages.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. The Life-or-Death Trials of Server Deployment
&lt;/h2&gt;

&lt;p&gt;If writing code is like fighting regular mobs, server deployment is the boss fight. I used an Alibaba Cloud 2-core 2G lightweight server with the Baota Panel installed. Here are the three massive pits I stepped into:&lt;/p&gt;

&lt;h3&gt;
  
  
  Pit 1: Uploading &lt;code&gt;node_modules&lt;/code&gt; directly to the server (Instant Crash)
&lt;/h3&gt;

&lt;p&gt;Initially, I tried to take a shortcut by zipping my entire local project and overwriting it on the Linux server. As a result, the Node service crashed on the spot, throwing an &lt;code&gt;invalid ELF header&lt;/code&gt; error.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;💡 Survival Guide:&lt;/strong&gt;&lt;br&gt;
Next.js's underlying dependencies (like the &lt;code&gt;sharp&lt;/code&gt; image compression library) are OS-specific! Transferring Mac/Windows compiled &lt;code&gt;node_modules&lt;/code&gt; to Linux will absolutely break your app.&lt;br&gt;
&lt;strong&gt;The correct, lightweight update flow:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run &lt;code&gt;npm run build&lt;/code&gt; locally.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Only zip&lt;/strong&gt; the &lt;code&gt;.next&lt;/code&gt; folder, &lt;code&gt;public&lt;/code&gt;, &lt;code&gt;package.json&lt;/code&gt;, and config files.&lt;/li&gt;
&lt;li&gt;Upload, unzip on the server, and run &lt;code&gt;npm install --production&lt;/code&gt; in the terminal to pull Linux-compatible dependencies.&lt;/li&gt;
&lt;li&gt;Restart the Node project. Boom, online in seconds!&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Pit 2: "Ghost Cache" (Code is updated, but the webpage is still old?)
&lt;/h3&gt;

&lt;p&gt;After deploying a newly developed image tool, I excitedly opened the site only to find the &lt;strong&gt;old version&lt;/strong&gt;! Even the XML Sitemap with the new routes hadn't changed.&lt;br&gt;
I initially thought the deployment had failed, but I eventually found the mole: &lt;strong&gt;Baota Nginx's default static caching&lt;/strong&gt;. Nginx would aggressively cache &lt;code&gt;.xml&lt;/code&gt;, &lt;code&gt;.css&lt;/code&gt;, and even pages for days at a time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;💡 The Cure:&lt;/strong&gt;&lt;br&gt;
Configure the HTTP headers in Next.js's &lt;code&gt;next.config.ts&lt;/code&gt; to forcefully attach a "do not cache" seal to frequently updated files. After making this tweak, every subsequent update went live instantly and smoothly.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pit 3: Disk suddenly hits 100% capacity, freezing the panel
&lt;/h3&gt;

&lt;p&gt;One night, Alibaba Cloud sent a critical alert: my 40GB hard drive was at 94% capacity, memory was in the red, and I couldn't even load my Baota admin login page!&lt;/p&gt;

&lt;p&gt;I connected via an SSH backdoor terminal, used the &lt;code&gt;bt 14&lt;/code&gt; command to rescue my panel login link, and ran &lt;code&gt;du -sh /* | sort -hr&lt;/code&gt; to investigate. Wow! The &lt;code&gt;/tmp&lt;/code&gt; folder in the root directory was hoarding a massive &lt;strong&gt;13GB&lt;/strong&gt; of data.&lt;br&gt;
It turned out that an automated tool (OpenClaw) had encountered a loop error days prior and went crazy writing temporary &lt;code&gt;.log&lt;/code&gt; files. Without regular cleanup, it literally bloated the server to death.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;💡 Rescue Plan:&lt;/strong&gt;&lt;br&gt;
Dive into the &lt;code&gt;/tmp&lt;/code&gt; directory, decisively delete those gigabyte-sized legacy temp logs (being extremely careful not to touch &lt;code&gt;.sock&lt;/code&gt; system communication files), and &lt;strong&gt;crucially, empty the Baota recycle bin&lt;/strong&gt;. Disk usage plummeted to 30%, and the server was fully revived!&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Final Thoughts
&lt;/h2&gt;

&lt;p&gt;Wrestling with servers, tweaking configs, clearing logs... while the process was full of nerve-wracking challenges, watching my website slowly pop up in Google search results and seeing the tools I envisioned running smoothly on a live server brings an unparalleled sense of accomplishment. That's the magic of building a product from 0 to 1.&lt;/p&gt;

&lt;p&gt;My tool site, Web Tools Hub (&lt;a href="https://web-tools.tech/" rel="noopener noreferrer"&gt;web-tools.tech&lt;/a&gt;), is still actively iterating. From PM to indie developer, the journey continues. If you're also building your own projects, or if you've run into similar DevOps issues deploying Next.js, drop a comment below. Let's navigate these technical traps together!&lt;/p&gt;

</description>
      <category>devops</category>
      <category>nextjs</category>
      <category>showdev</category>
      <category>sideprojects</category>
    </item>
  </channel>
</rss>
