開發歷程:從單頁應用到多頁網站,為了被搜尋引擎看見

這是 LocalPapa Notes 開發紀錄系列的第四篇。前三篇都在講「做了什麼工具」;這一篇不一樣——它講的是一個架構上的轉向,也是讓前面那些工具終於能「被看見」的關鍵一步。

漂亮,但沒人找得到

最早的 LocalPapa 是一個單頁應用(SPA, Single-Page Application)。所有工具都擠在同一個網址底下,靠 JavaScript 切換畫面——體驗很滑順,工程上也很「現代」。

問題是:搜尋引擎幾乎看不到它。

對 Google 的爬蟲來說,整個網站只有一個網址、一個標題、一段描述。底下不管有合併 PDF、剪輯 MP3 還是壓縮圖片,在索引裡都「不存在」——因為那些內容是點擊之後才由 JS 動態生出來的。

結果就是:我們做了一堆好用的工具,卻沒有任何一個能透過搜尋被人找到。對一個想靠自然流量成長的工具站來說,這是致命的。

核心決定:把一頁拆成很多頁

解法聽起來簡單,做起來是一次重構:從 SPA 改成多頁網站(Multi-Page),讓每一個工具都擁有自己獨立的網址

這就是 tools/ 目錄的由來。我們把原本擠在 SPA 裡的 8 個 PDF 工具,一個個實體化成獨立的 HTML 檔案——merge-pdf.htmlsplit-pdf.htmlrotate-pdf.html……每個都是一個真正的、可以被爬蟲直接讀到的網頁。

怎麼拆,又不重複造輪子

拆成幾十個獨立頁面,最怕的就是「每頁都複製一份導覽列和樣式」,日後改一個地方要改幾十次。所以拆分的同時,我們把共用的部分封裝起來:

  • tools-common.css:所有工具頁共用的樣式,確保視覺一致。
  • tools-common.js:共用的工具列、深色主題、語言切換邏輯。

每個工具頁只放自己獨有的內容,共用行為一律引用這兩個檔案。這樣既有獨立網址的 SEO 好處,又沒有維護幾十份重複程式碼的惡夢。(你現在讀的這個部落格,用的也是同一套 tools-common ——多頁、靜態、共用底層,一脈相承。)

讓每一頁都「會自我介紹」

有了獨立網址還不夠,得讓每一頁主動告訴搜尋引擎「我是誰」。所以每個工具頁的 <head> 都補上:

  • 獨立的 <title><meta description>:針對該工具的關鍵字撰寫。
  • Schema.org 結構化資料(JSON-LD):以 SoftwareApplication 型別標註,強化 Google 對「這是一個免費瀏覽器工具」的辨識。
  • 並建立 sitemap.xml,讓爬蟲能完整走訪所有頁面。

換句話說,每個工具從「藏在 SPA 裡的一個分頁」,升級成一個會自我介紹的落地頁(Landing Page)

首頁的角色也變了

首頁不再是「工具本身」,而是改造成一個工具聚落——一格一格的工具卡片網格(Grid of Tool Cards),配上 hover 時的微動畫。它的新任務是導覽與聚合:把訪客(和爬蟲)分流到各個獨立的工具頁。

學到的事

  • 好體驗 ≠ 找得到。 SPA 的順滑是真的,但如果搜尋引擎看不到你的內容,再好的工具也是孤島。可被發現性(discoverability)本身就是一種功能。
  • SEO 不是事後補的標籤,是架構決定。 真正讓搜尋引擎看見的,不是塞關鍵字,而是「每個內容都有自己的網址」這個結構性選擇。
  • 拆分要配封裝。 多頁帶來 SEO,共用檔案(tools-common)守住可維護性——兩者要一起做,缺一不可。
  • 長尾關鍵字是工具站的養分。 「合併 PDF 不上傳」「線上 MP3 剪輯」這類具體搜尋,每一個獨立落地頁都能去承接。

一以貫之的問題

前幾篇問的是「能不能在瀏覽器裡完成」。這一篇問的是它的下一半:做好了,要怎麼讓需要的人找到?

答案是:把架構本身,變成可以被搜尋引擎讀懂的形狀。

下一篇開發紀錄,我們會走到讓網站能自給自足的一步——廣告變現與合規配置。想追蹤系列?把 LocalPapa Notes 加入書籤吧。

Dev Log: From Single-Page App to Multi-Page Site, to Be Found by Search Engines

This is the fourth post in the LocalPapa Notes dev-log series. The first three were about what tools we built. This one is different — it's about an architectural pivot, and the key step that finally let all those earlier tools be found.

Slick, but nobody could find it

The earliest LocalPapa was a single-page application (SPA). Every tool lived under the same URL, with JavaScript swapping the view — smooth experience, nicely "modern" engineering.

The problem: search engines could barely see it.

To Google's crawler, the whole site was one URL, one title, one description. Whether merge-PDF, MP3 editing or image compression sat underneath didn't matter — in the index they simply "didn't exist," because that content was only generated by JS after a click.

The result: we'd built a pile of genuinely useful tools, and not one of them could be discovered through search. For a tool site trying to grow on organic traffic, that's fatal.

The core decision: split one page into many

The fix sounds simple but was a full refactor: go from SPA to a multi-page site, giving every single tool its own dedicated URL.

That's where the tools/ directory came from. We turned the 8 PDF tools once crammed into the SPA into individual HTML files — merge-pdf.html, split-pdf.html, rotate-pdf.html… each a real web page a crawler can read directly.

How to split without reinventing the wheel

The danger with dozens of separate pages is copy-pasting a navbar and styles into every one — change one thing later, edit it dozens of times. So as we split, we encapsulated the shared parts:

  • tools-common.css: shared styles across all tool pages for visual consistency.
  • tools-common.js: shared toolbar, dark theme, and language-switch logic.

Each tool page holds only its own unique content and references these two files for shared behaviour. That captures the SEO benefit of separate URLs without the nightmare of maintaining dozens of duplicated copies. (The blog you're reading uses the same tools-common — multi-page, static, shared foundation; same lineage.)

Making every page introduce itself

Separate URLs aren't enough; each page has to actively tell search engines "who I am." So every tool page's <head> gained:

  • A dedicated <title> and <meta description>, written for that tool's keywords.
  • Schema.org structured data (JSON-LD), marked up as SoftwareApplication, reinforcing to Google that "this is a free browser tool."
  • And a sitemap.xml so crawlers can fully traverse every page.

In other words, each tool was upgraded from "a tab hidden inside an SPA" into a self-introducing landing page.

The homepage's role changed too

The homepage stopped being "the tool itself" and became a village of tools — a grid of tool cards with hover micro-animations. Its new job is navigation and aggregation: routing visitors (and crawlers) out to each independent tool page.

What we learned

  • Good UX ≠ findable. The SPA's smoothness was real, but if search engines can't see your content, even great tools are islands. Discoverability is itself a feature.
  • SEO isn't tags bolted on afterwards — it's an architectural decision. What actually makes search engines see you isn't stuffing keywords; it's the structural choice that "every piece of content gets its own URL."
  • Splitting must come with encapsulation. Multi-page brings SEO; shared files (tools-common) preserve maintainability — you do both, or neither works.
  • Long-tail keywords are a tool site's nutrition. Specific searches like "merge PDF no upload" or "online MP3 trimmer" each need a dedicated landing page to catch them.

The same question, the other half

The earlier posts asked "can this be done in the browser?" This one asks its second half: once it's built, how do the people who need it find it?

The answer: turn the architecture itself into a shape search engines can read.

In the next dev log, we reach the step that lets the site sustain itself — ad monetisation and compliance. Want to follow the series? Bookmark LocalPapa Notes.

探索 39+ 個隱私優先的瀏覽器工具
全程本地運算、檔案不上傳。
前往 LocalPapa →
Explore 39+ privacy-first browser tools
Everything runs locally — your files never leave your device.
Visit LocalPapa →

想看英文版?點右上角 EN 切換語言。

Prefer Chinese? Tap at the top-right to switch.