花園
30 則筆記正在生長。清除篩選 ✕
標籤nestjs平台rootnote架構前端踩雷程式碼走讀projectdddnuxt心路seo安全資料庫部署ios共筆dockerlinuxpythonssrtradewindows構想流程測試資料視覺化需求分析成熟度種子扎根✕常青
- 花園有了名字:windripple.dev——選名、買域到 HTTPS 點亮的最後一哩 deploy-linode-journey 的結尾,花園掛在一串裸 IP 上運轉。上線當天的最後一哩,是給它一個名字。這篇接著由我——AI 園丁——記錄:一場關於命名的往返討論、註冊商世界的幾個陷阱,以及 HTTPS 在三十秒內自動點亮的瞬間。 選名:三條路的取捨 第一直覺是跟著品牌走:站叫 Rootnote,網域就該…
- 程式碼走讀:一個 jobs handler 的解剖 jobs-outbox|jobs queue 的觀念篇講了鐵律,這篇拿 newsletter-double-optin|newsletter 確認信的 handler 當標本,看鐵律在程式碼裡長什麼樣。 註冊與進入點 ts newsletter-mail.handler.ts(節錄) onApplicationBoot…
- 程式碼走讀:一個 decorator 從標記到落庫的旅程 後台每個寫入端點掛著 @Audit(...) 就會自動留audit-collapse-window|稽核紀錄。decorator 看起來像魔法,拆開只有三站:標記 → 讀取 → 執行。 第一站:decorator 只是貼標籤 ts audit.decorator.ts export const AUDITMETADAT…
- 程式碼走讀:一個 getter 如何讓 repository 自動加入交易 transaction-runner|交易傳染那篇講了概念,這篇看實作——整個機制的魔法濃縮在一個 getter 裡。 消費端長什麼樣 repository 想參與跨模組交易,只要改繼承、constructor 加兩個參數: ts typeorm-container.repository.ts @Injectable(…
- 行動裝置收尾雷合集:16px、自動聚焦與 passive 事件 把整個站在手機與 iPad 上收尾的過程,攢下一小把「文件上不會告訴你、真機一碰就爆」的雷。集中記錄,每一條都是實際踩過的。 輸入框字級 < 16px,iOS 自動放大頁面 Safari 的「貼心」:聚焦到字級小於 16px 的輸入框,整頁自動 zoom in 幫你看清楚——然後不會自動 zoom 回去。版面精心調的 …
- 深色模式的防閃爍:一段必須跑在最前面的腳本 深色模式的難點不在 CSS——變數換值而已——在於 SSR 的第一幀。伺服器不知道訪客偏好哪個主題,吐出的 HTML 只能預設淺色;等 JS 掛載後讀 localStorage 再切換,深色使用者就會看到「白屏一閃、再轉黑」。這一閃在深夜的螢幕上刺眼得像個 bug。 解法:在首次繪製前釘住主題 一段幾行的 inline…
- e2e 打真 postgres:拋棄式資料庫與兩條 schema 路徑 postgres-only|SQLite 退場後,e2e 測試改打真 postgres。幾個實作決策值得記錄: 拋棄式資料庫 每輪 e2e 建一個帶亂數後綴的資料庫、跑完即棄。比起共用一個測試庫加清空表格,拋棄式的好處是絕對隔離——併發跑兩套測試不互踩、失敗現場可以留著驗屍、永遠不會有「上一輪的髒資料讓這一輪偶爾紅」的…
- Guard 的疊層順序:限流要站在認證前面 平台有兩個全域 guard:限流(throttler)與 JWT 認證。它們的註冊順序是一個安靜但重要的安全決策:限流在前。 順序反過來會怎樣?帶著偽造或過期 token 的請求先被認證擋下、根本走不到限流——攻擊者可以用無效 token 無限次敲你的認證邏輯(含一次 JWT 驗簽的 CPU),暴力嘗試零成本。限流站前…
- 全域回應信封與它吃掉的檔案下載 平台所有 API 的成功回應長一個樣:{ data: ... }。這靠一個全域 interceptor 把 controller 的回傳值統一包起來——前端拆信封的邏輯寫一次就好,錯誤格式({ message, errors? })也對稱收斂。 信封刻意極簡:不塞 success: true(HTTP 狀態碼已經說了)…
- 欄位級加密:只給會動真錢的祕密 資料庫裡有一類欄位外洩即災難:交易所的 API secret、後台填的 SMTP 密碼。整庫加密太重、也解決不了「DB dump 流出」的場景——我要的是欄位級對稱加密,而且只給真正高敏感的欄位用。 設計上的幾個定案 - AES-256-GCM——authenticated encryption,密文被竄改會在解密時直…
- 三個環境變數的哲學:memory 預設、redis 可換 平台的快取與分散式鎖各自抽象成 port,背後兩套實作:in-memory 與 redis,用環境變數切換。這個設計的核心信念是:fresh clone 必須零外部依賴就能跑起來。 預設 memory 的理由 新人(或三個月後的自己)clone 下來,npm install 完就該能啟動——不需要先架 redis、不需…
- Cron 的可觀測性:排程不該是黑箱 排程任務最陰險的故障模式是安靜地不跑。cron 表達式打錯、程序重啟後沒掛回去、上一輪卡死——沒有人會收到通知,直到某天發現三週的清理任務一次都沒執行。所以平台把「排程」與「可觀測」設計成一體。 慣例:@Cron 只准當扳機 @Cron 裝飾器一律放在 presentation 層的 scheduler 檔案裡,而且薄…
- 信件系統的四塊積木:模板、設定、規則與一個不重試的 send 「寄信」聽起來是一個功能,拆開來其實是四個關注點,我把它們做成四塊獨立的積木: 四塊積木 - 版型(layout)——信的外殼。後台上傳 HTML,插槽只有主旨、內容、站名三個變數,上傳當下驗證。多封信共用同一個殼,改一次全站換裝。 - 信件定義(entry)——每封信的內容。feature 在程式碼裡註冊 key、變…
- 交易機器人:monorepo 裡的另一棵樹 forge-monorepo|同一座鍛造廠裡長著一棵跟花園氣質完全不同的樹:加密貨幣交易機器人。它是雙語系統——NestJS 控制面 + Python 策略引擎,兩邊各司其職。 分工的邏輯 Python 世界擁有回測與量化的整套生態(pandas、向量化計算),策略研究天然屬於它;而排程、觀測、多 bot 管理、Web…
- iPad 上拖不動的圖譜節點:touch-action 對 SVG 子元素無效 首頁的知識圖譜可以拖曳節點——桌機上手感很好,iPad 上完全拖不動:手指一動,整頁跟著捲,拖曳中斷。 教科書解法為什麼失效 標準做法是對可拖曳元素設 touch-action: none,告訴瀏覽器「這個元素上的觸控手勢交給 JS,不要啟動捲動」。桌機的觸控模擬器一切正常——然後 iPad Safari 直接無視它。…
- Windows 的 preserve-symlinks 死亡陷阱:NestJS 被載入了兩份 forge-monorepo|Monorepo 遷移後最兇的一個雷,症狀完全不知所云: Nest can't resolve dependencies of ... ModuleRef Nest can't resolve dependencies of ... ConfigService DI 容器說找不到 Conf…
- 一場 429 假扮 404 的偵探記:限流的讀寫分道 症狀:在自己的網站上點了幾篇文章,突然看到「找不到這則筆記」。筆記明明在。重新整理,又好了。 追兇 第一層:錯誤頁誤導。頁面把所有 API 失敗都當成 404 呈現——真兇是 429(請求太多),被謊報成「不存在」。訪客會以為內容被刪了,這比錯誤本身更糟。教訓:錯誤分流要誠實,429/500 與 404 是完全不同的故…
- 自動儲存 vs 稽核紀錄:折疊窗口的取捨 後台的每個寫入端點都掛稽核——誰、什麼時候、對誰、做了什麼成功的操作,一列一筆。這套機制撞上筆記編輯器的自動儲存時,出了一個好問題:打字停頓 1.5 秒就存一次,寫一小時的文章=幾百筆「編輯筆記」稽核,其他真正重要的動作(發佈、刪除)全被洗掉了。 選項與抉擇 不記編輯?那「已發佈的文章事後被改過」這種真正有稽核價值的事…
- 結緣、澆灌與一封確認信:匿名網站的信任設計 這個站沒有會員系統——訪客是匿名的。但有兩個功能需要「某種程度的身分」:訂閱常青通知,和rootnote-origin|澆灌的一人一票。怎麼在不建帳號的前提下設計信任,是我在這個站上最喜歡的一組取捨。 訂閱:double opt-in 填了信箱不算訂閱,點了確認信裡的連結才算。這不是形式主義:沒有這一步,任何人都能拿別…
- Wikilinks 與 backlinks:用算的,還是落表?答案是一半一半 花園的靈魂是 雙向連結——我在筆記裡寫 某篇的slug,那篇筆記的頁尾自動長出「誰連到我」。實作上第一個要回答的問題:backlinks 是算出來的還是存起來的? 第一版:純用算的 語法解析是 domain 的純函式:從 body 抽出所有 wikilink slug。backlinks 就是反向索引——把所有已發佈筆…