@Airmauve
霧光創辦人 · 把 Airmauve 從零做到一。Mark what matters.
2026 年加入 · 35 筆公開事件
之前在 home screen 上比薄荷綠那顆小一截看起來軟掉。把 sprout scale 從 1.45 拉到 1.72,莖跟葉緣的線也加粗了一點,小尺寸下終於不糊了。順便重新出了一整套 PNG / favicon / PWA icon。
原本的設定頁有自由 hex 色碼輸入,結果一堆人選了刺眼的螢光色。砍掉自由輸入只留精挑的 8 色 swatch,旁邊加 live preview 卡片即時看效果。看得到才會選得好。
把每個 tier 內的徽章重新排成一致順序(累積 → 連續 → 挑戰 → 廣度 → 見證 → 社群/旅程),每個 tier 像走在同一條 lane 上,grid 從上到下看起來終於對齊。
舊圖兩個點像眼睛、那條虛線弧像哭臉的嘴,看了好幾天才驚覺。重畫成兩個小人走在透視小路上、頭頂一道珊瑚色弧線連在一起,呼應品牌的「與我同行」。
tier 後續:Trace 的 OG 卡帶浮水印、Story+ 解鎖自訂主題色、Odyssey 拿到 Streak 保鏢日(漏一天不斷 streak)。
一覺醒來看 stats:All time 23d current streak、23d longest、388 sessions、137k messages、55.9M tokens(~358× Pride and Prejudice)。比 19 天前那次 +8d streak、+157 sessions、+15.5M tokens — 中間每天都有 carry。Favorite 也從 Opus 4.6 換成 4.7。1AM peak 始終如一,夜貓子穩定輸出中。
為 first_step 徽章 SVG 改了五次:重畫腳印、嬰兒腳形狀、兩個錯位鏡像、最後乾脆換成走路小人。覺得腳印一直畫不滿意,圖形愈簡愈難,反覆 polish 才收得乾淨。
1200×630,珊瑚橘漸層 + 「走過的路,都算數。」slogan。寫了 scripts/generate-og-default.mjs,以後改色/文案直接重跑。配合白天接的 SEO,任何頁面被分享出去都有像樣的封面了。
加了 completedAt 到 Lane 跟 CoJourney,標題下面會顯示「Day N · 從 YYYY/MM/DD 開始」。按完成就凍結成「共 N 天 ✓」。Airmauve 這條測一下,從 4/24 第一筆事件算 Day 3,對。 之後改 NI Infinite 那條(已經 83 筆)應該會看到 Day 大概 3 位數。
時間軸新增「並排」模式,可勾選最多 5 個劇情線/類別/共同旅程同時看,事件按日期對齊。磚牆密度做兩層:預設只露單行 90 天總覽乾淨,點開「看各欄細節」展開每欄 8 週的 GitHub 風格 grid。設計從 mockup 跑了三輪迭代才定案 — 從原本 56 天改成 90 天總覽 + 56 天細節,共同旅程也加入欄位選擇器。先後做了單欄加寬、複製事件、多選批次編輯,現在並排視圖到位後,時間軸的彈性算是補完了。
把之前那個 ParallelTimelineView 正式接到時間軸 header — 多了「| 單欄 / ≡≡ 並排」切換按鈕,選哪個 + 並排時挑了哪幾欄,都會記在 localStorage,下次回來還在原本的模式。EventCard 也順手加了 compact 模式,並排時左邊那顆 emoji 節點和 checkbox 不會擠進來搶位置。
三個功能一次到位。📋 複製按鈕:原事件內容帶進去,日期換今天,天氣重抓。☑️ 多選模式:手機長按、桌面 hover checkbox,選中後底部浮出 action bar,可改類別、移劇情線、改公開/私人、批次刪除。另外把所有個人成就紀錄搬進新建的「Airmauve霧光」劇情線,這條線以後就是霧光自己成長的紀錄。
做了 10 個品牌 SVG 頭像 (晨霧/小苗/燈塔/暖陽/靜湖/同行/觀月/爐火/山徑/見證) 新用戶註冊隨機分配。schema 加 welcomedAt 欄位,首次登入會跳一次溫馨 modal,介紹時間軸/回顧/共同旅程三件事,按下「開始記錄」標記已看過。OAuth 也統一 override 為霧光預設,品牌一致性優先。/settings 加「從預設挑頭像」picker。
一口氣把 Batch D 跟 B 塞進去:Quick Log FAB 讓記錄變成 5 秒的事、Streak 連續記錄計數、/dashboard 年度熱圖、個人頁 IG grid/時間軸雙視圖切換、Pin 到個人頁、On This Day 引用回顧、AI 年度敘事(Opus 4.7)。另外伺服器端搜尋補完、多照片 Carousel 上線、Sentry + Umami 接好。最大的一版,壓力很大但全過了。
之前一條線什麼都看起來一樣 — 現在事件間距依時間差視覺化、跨日有完整日界線(2026/04/22 週三)、節點變成類別 emoji 圈、ring 顏色傳達狀態(公開/挑戰/私人)、今天錨點脈動。霧光的時間軸第一次像時間軸。
事件可以選歸屬到一條劇情線(感情/工作/健身/寫作…),時間軸用顏色彩條 + chip 標記。schema 加 Lane model + Event.laneId,/settings/lanes 管理 + form / filter 都接好。跟「類別」分開:類別是分類標籤,劇情線是敘事線。
/settings 加 coral 邊框「資料與帳號」區塊。下載我的資料 → 拿到完整 JSON dump(profile/events/categories/comments/likes/journeys/reminders)。永久刪除帳號 → 兩段 confirm + signOut + 全 cascade 清掉。在他人事件下的留言會 anonymize 不會消失。
P0 — 之前頭像/事件照片只能貼 URL。Cloudflare R2 走 S3-compatible API,presigned URL 讓瀏覽器直接上傳不經後端。lib/storage.ts + /api/upload/sign + useUpload hook。/settings 頭像欄位多了「📷 改傳檔案」按鈕。沒設 R2 env 時 graceful 隱藏。事件照片 UI 待後續整合到 timeline form。
Comment.parentId nullable + self-FK CASCADE,DB 直接 push 到 Railway prod 零資料風險。後端把回覆的回覆 pin 回最上層 parent — UI 永遠兩層深、不會無限縮排。每則留言旁加「回覆」按鈕展開 inline 框,reply 用 cream 底色細線縮排。
/e/[id] 加上愛心按鈕,接通了 Like schema 跟前端。 實作: - POST /api/events/[id]/like 切換 liked 狀態,回傳 { liked, count } - 未登入點下去自動帶到 /login?callbackUrl=/e/<id>(而不是直接 401) - 私人/不存在的事件 404,維持跟 /e/[id] 同樣的隱私契約 - 客戶端 optimistic UI:點下去馬上翻紅 + 數字 +1,失敗才 revert 下一步可以接 Comment thread,或先停這。 PR #28。
OG 卡 /api/og/event/[id] 早就在,但點進去沒有真實的頁 — 分享出去 thumbnail 是漂亮的成就卡,點進來卻是 404。今天補上 /e/[id] 公開事件頁。 設計很單純:標題 + mood + 日期 + 地點 + 天氣 + 類別 + 描述,底下作者卡帶頭像跟「看更多 →」連到 /u/<username>。私人事件回 404(不洩漏存在),公開事件 metadata 帶上 OG 圖跟 Twitter card。 順便讓 /u/<username> 上每張事件卡都包一個 Link 連到 /e/[id],點擊行為閉環。 PR #27。
PR #23 讓使用者能在 /settings 貼頭像 URL,但公開 profile 的 OG 卡還是只會出姓名首字母 — 等於設了頭像也看不到。這次補上。 實作很短:OG route 多撈 user.image,有圖就 render <img> 圓形 crop 168×168,沒有就 fallback 回 initials chip。next/og 的 Satori 在 render 時才去抓圖,所以改頭像下次分享就會出新圖,不用 cache busting。 剛才用 Picsum 隨機圖測過 — 圓形 crop 跟原本 initials 版的視覺是同一條線,不違和。 PR #25。
今天最後一塊 polish:把共同旅程變成真的能管的東西,而不是只能單向加入。 - **編輯旅程**:創建者可以改名稱、描述、起訖日,inline form 開在詳情頁 - **離開旅程**:成員(非創建者)可以自己退出,footer 一個按鈕 + 確認框 - **踢人**:創建者可以把成員從旅程裡移掉,成員列表上每個非創建者旁邊出現 ✕ - **刪除旅程**:創建者按下去整段消失。schema 已經有 cascade,member 跟著刪;旅程內的事件 coJourneyId 變回 null(透過 SetNull),不會丟事件 API 端 4 條新路:POST /leave、DELETE /members/[memberId]、PATCH /[id]、DELETE /[id]。所有 destructive 都有 confirm,創建者不能離開自己創的旅程(改用刪除),也不能被踢。 PR #24 等 merge。
做了 /settings 頁,終於可以動 User schema 上那些一直存在但沒地方改的欄位: - username — 從 OAuth 註冊時自動產生的 'invictnox-9f35' 拍版改成 'invictnox',profile URL 直接跟著變 - bio — 280 字以內,會出現在公開 profile 跟 OG 卡上(OG 卡是動態生成的,改了下次 render 就會抓到新值,不用做 cache busting) - 顯示名 + 頭像 URL — 同個頁面一起做掉 backend 是 GET/PATCH /api/me,zod 把關 username 格式跟 bio 字數,Prisma 唯一性違反(P2002)轉譯成 409 username_taken,UI 顯示「這個 username 已經被別人佔用了」。 頭像目前只能貼 URL,檔案上傳要等之後決定 R2 / S3 再做。 入口加在兩個地方:時間軸 header 的 ⚙️(md+)、跟看自己 /u/<username> 時的「⚙️ 編輯個人設定」連結。 實機驗證了一輪 — 我順手把自己的 username 從 'invictnox-9f35' 改成 'invictnox',OG 卡跟 profile 頁立即反映。 PR #23,跟 PR #22 一起 merge。
把 Co-journey 從只有 schema 變成真的能用 — 創建、列表、詳情、邀請連結、加入,全部一條龍。 簡單說: - /journeys — 列表 + 建立旅程的 inline form,看到自己創建跟參加的全部 - /journeys/[id] — 詳情頁,創建者能產生/複製/輪替/停用邀請連結;成員清單帶 avatar - /join/[token] — 收到邀請的人點進來看到 preview,登入後一鍵加入,已經是成員就直接跳進去 - 順手把 /login 改成支援 ?callbackUrl=,所以邀請連結 → 沒登入 → 登入 → 自動跳回 join 頁這條路通了 - timeline header 加了「🤝 共同旅程」入口 DB 已經 push 過 inviteToken 欄位,prod 那邊 Railway 部署時會跟著同步。 PR #20。
做了一個 /review 頁,進去就看「過去這天我做過什麼」— 同個 MM-DD 在歷年出現過的事件全部撈出來,按年分組,標題用「今天」/「去年的今天」/「N 年前的今天」。 實作很輕,server component 直接打 prisma 撈,JS 端 filter 月日 — 反正一個人的事件量還不會大到需要 SQL EXTRACT。卡片重用 PublicEventCard,維持時間軸跟 profile 同個視覺語言。 時間軸 header 也加了個小按鈕「🪞 今日回顧」,sm+ 才出現,不擠手機版。 PR #19 等 merge。
之前 /u/<username> 分享出去就是那張無聊的 og-default.png,現在改成動態卡 — 跟事件分享卡同一套配色 (珊瑚橘 / 奶油白 / 墨色 / 薄荷綠),但中間是大頭像 + 姓名 + handle + bio,底下一條最近用過的類別 emoji 條。 實作在 app/api/og/profile/[username]/route.tsx,套 next/og 的 ImageResponse。同個域名連到 og-image.com 之類的測試器就能直接 preview。看了一張用我自己的 username 渲染的 1200×630,字體比例還順。 PR #18,等 merge 就上。
把 next-intl 的 localePrefix 從 always 切到 as-needed,主要是 SEO 考量 — 根網址 / 直接出中文,英文還是 /en/...。Google 的 "different URLs per language" 指引依然滿足,但 zh 的 SEO 權重集中在根。 PR #16 已開,等 merge 進 main 自動部署到 airmauve.com。後續分享 /u/<slug>、/timeline 這些 URL 都不會帶 /zh 前綴了,讀起來自然多。 順手把 Claude 加成「每個 commit 都要記到霧光」的 workflow,以後這條時間軸就會自動跟著開發節奏長。
跨日凌晨把自訂網域接上。Cloudflare 的 apex CNAME 被前端 form 偷偷 Punycode 成 xn--oh7c,直接用 API 刪掉重建成 airmauve.com → mw1px0cl.up.railway.app。打開 proxy 讓 CNAME flatten 出 A 記錄,Cloudflare edge 接手 TLS,終於從 .railway.app 走到正港的 airmauve.com。 從 /zh 的米色首頁,到 /u/invictnox-9f35 的公開 profile,到 /api/og/event/[id] 的 1200×630 成就卡 — 現在都掛在 airmauve.com 底下。
修了 dark-mode 下文字不可見、類別下拉重複 4 次、今天事件誤入未來區的時區 bug。E2E smoke 全通。到了這一刻,Airmauve 不只是規格書,而是活著的 app。
Railway airmauve 專案 + Postgres + 自動 domain。踩到 Node 18 / Prisma 7 + --skip-generate flag 被移除 + NextAuth trustHost 三個坑,三個 hotfix PR 連發,20:17 正式跑起來。
第一個版本部署到 Railway,本地到生產全部一天內搞定。
About / Contact 區塊填入正式聯絡資訊。
公司網站 hero 文案定調。
Invictnox 集團主站起點 — 丁格鳥公司頁第一行 commit。