TreeMap
A free, open-source disk-space visualizer. Squarified treemap, duplicate hunting, disk-full forecasting, and cleanup that only ever moves files to the Trash.
翻譯準備中
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
A real-life RPG. Your life is the game; you are the main character.
▶ Play it: life-os-game.vercel.app (phone and desktop. Play instantly as a guest, and sync across devices when you want to)
Your real goals become quests. Doing them earns XP. XP grows a character with levels, attributes, titles and a history worth looking back on. A Game Master watches your progress, reacts to it, and nudges you toward the things you've been avoiding.檢視完整 README ↗A real-life RPG. Your life is the game; you are the main character.
▶ Play it: life-os-game.vercel.app (phone and desktop. Play instantly as a guest, and sync across devices when you want to)
Your real goals become quests. Doing them earns XP. XP grows a character with levels, attributes, titles and a history worth looking back on. A Game Master watches your progress, reacts to it, and nudges you toward the things you've been avoiding.
LIFE//OS isn't a habit tracker with a coat of paint. There are no streaks to lose and no guilt. Coming back after time away is rewarded, not punished. Small deeds get a quiet nod, and big ones get a moment.
Every quest has a tier. The tier sets the reward and how the game reacts.
| Tier | XP | Meant for | Reward |
|---|---|---|---|
| Tiny | 10 | Two minutes. Drink water, make the bed. | A soft tick |
| Quest | 50 | A real session. Practice, study, train. | A chime and a toast |
| Challenge | 150 | The hard thing you keep putting off. | A bigger chime |
| Boss | 500 | A milestone. Ship it. Finish it. | Must be held to defeat. Full-screen moment |
Quests are either one-time or daily rituals that reset each day. Retiring a quest costs nothing, because priorities change.
Rested XP: if you come back after 3+ days away, your first deed earns +50%.
Each quest trains one of five attributes. The game suggests one based on the quest title.
| Attribute | Domain | |
|---|---|---|
| STR | Strength | Movement, exercise, physical challenges |
| INT | Intellect | Study, learning, technical work |
| DEX | Dexterity | Practice, instruments, craft |
| VIT | Vitality | Sleep, food, recovery, routines |
| CHA | Charisma | People, voice, courage |
The attribute radar shows your character's shape at a glance.
Two standard quests reach level 2. After that the curve stretches: level 10 → 11 takes 1,310 XP. Attribute rank r needs 25·(r−1)² attribute XP.
Long-term goals are broken into chapters that are cleared in order. Each chapter is worth +150 XP. Finishing a campaign adds a +500 XP bonus and a full-screen ceremony.
There are 18 achievements, 7 of them secret: you find those by playing, not by reading a checklist. Several grant equippable titles that appear under your name.
Brawler (STR/VIT), Archer (DEX/STR), Mage (INT/DEX), Bard (CHA/DEX), Monk (VIT/INT) or Wanderer (+7% everything). A class gives +20% XP on its primary attribute and +10% on its secondary, and shapes the daily contracts. It can be changed any time; past XP stays as earned.
Every day the system posts three contracts that can't be edited: a small step for the weakest attribute, a session in today's focus interest (or the class's craft), and a Game Master challenge — usually the once-quest you've avoided longest. They're the only source of a fixed daily XP budget (100 XP at level 1, up to 400). Missing them costs nothing. Boards are generated deterministically from the character and the date, so every device agrees.
Players tell the game what they love doing — from a catalog of ~26 interests (guitar, Rubik's cube, chess, running, coding, cooking…) or in their own words — and how experienced they are. Contracts and Game Master suggestions are then built around those interests: a guitarist gets guitar contracts, a cuber gets cubing ones.
src/engine/interests.ts and interestCatalog.ts.Boss quests can have multi-day HP (up to 10 strikes): each strike earns 80 XP and the final blow the full boss reward. Weekly goals (up to three, e.g. "Guitar 3×") pay a bonus when met and simply reset on Monday if not.
A local narrator with a voice. It greets you based on how long you've been away and reacts to what you just did. It spotlights a quest you've been avoiding and offers a "side story" to get you started. It also proposes new quests aimed at your weakest attributes.
It is deterministic and runs entirely on-device: no LLM, no network calls.
Your history, month by month: XP earned, levels gained, a calendar heat map, rituals kept, your biggest win, and the full log.
Rewards are tiered on purpose:
All sound is synthesized with WebAudio (no audio files) and can be muted.
LIFE//OS is local-first: the game always runs on your device, instantly and offline. Syncing across devices is optional.
| Guest save | Synced account | |
|---|---|---|
| Account needed | No. Open the app and play | Email + password (no confirmation email needed) |
| Where the save lives | This browser only | Your account in the cloud, cached on each device |
| Works offline | Yes | Yes. Progress queues and syncs when you're back |
| Phone + laptop | Separate saves | The same character |
| Clearing site data | Erases the character ⚠️ | Harmless. Sign in again and it all comes back |
Guest → account: play as long as you like, then open ☰ System and choose Create account & sync. Your save is backed up, uploaded, verified against the server, and only then is the device switched over. If anything fails partway, your guest save is untouched and you can retry safely, because uploads are idempotent.
If you sign in on a device that already has a different guest character, you choose what happens: merge its progress into your account character, or keep the account character and leave the guest save as an on-device backup. Nothing is ever silently overwritten.
The status light in the top bar always tells you where your progress is: ● SYNCED · ↻ SYNCING · ○ OFFLINE · SAVED LOCALLY · ! SIGN IN TO SYNC · ◇ GUEST SAVE.
Your data is yours. Export a versioned save file at any time. Importing into an account can only merge, never overwrite. Before anything that could replace a save (import, restore, new game, sign-out with unsynced progress), an automatic on-device backup is taken, and you can restore it from ☰ System → Backups.
IDENTITY (Supabase Auth: email + password)
│
USER · PROFILE
│
LIFE//OS GAME ENGINE ← unchanged; the only place game rules live
│
EVENT STORE
┌─────────┴─────────┐
local cache + cloud event log
offline queue (Postgres, per-user, RLS)
src/
engine/ pure, deterministic game rules: no React, no DOM, fully tested
types.ts events (source of truth) → projected state → effects
commands.ts validate intent → produce events (clock + ids injected)
project.ts fold events into state; emit effects for the UI
validate.ts structural validation of untrusted events (imports, cloud)
leveling.ts achievements.ts titles.ts gameMaster.ts chronicle.ts infer.ts
store/ GameStore, guest persistence, save files, on-device backups
sync/ accounts & sync (knows nothing about game rules)
accountStore.ts local cache + offline queue (same EventStore interface as guests)
syncEngine.ts push pending → pull after cursor → converge
migration.ts guest → account linking (backup, upload, verify)
cloud.ts Supabase adapter (lazy-loaded)
app/ Runtime: which save is active, sign in/out, import, restore; sync scheduler
ui/ React: HQ panels, views, celebration director, save & account UI
supabase/migrations/ the database schema, RLS policies and RPCs
Event-sourced. No number is ever mutated directly:
COMMAND → validate → EVENT → append to log → project → EFFECTS → celebrate
Completing a quest appends an event. That event becomes XP transactions, and the transactions are projected into level, attributes, achievements and titles. This gives you history, undo (by replaying the log), and auditability. Replaying a log always reproduces exactly the same state.
Because the game is event-sourced, sync moves events, never derived state:
device: pending events ──push_events (idempotent)──▶ cloud assigns per-user seq
device: pull seq > cursor ──▶ cache ──▶ replay ──▶ identical state on every device
| Table | Holds | Access |
|---|---|---|
auth.users | identity (managed by Supabase Auth) | Supabase only |
profiles | user_id, display_name, timestamps | read own; update own display_name |
game_events | user_id, event_id, seq, type, at, payload (the full engine event), schema_version, device_id | read own; no direct writes |
sync_state | per-user last_seq counter | read own; no direct writes |
The only write paths are two SECURITY DEFINER functions that act strictly on auth.uid(): push_events(events, device_id) and delete_my_account(). Events are immutable, and history is corrected by appending (deed.undone).
INSERT/UPDATE/DELETE any table, even their own rows.React 19 · TypeScript (strict) · Vite · Vitest · plain CSS · Supabase (Postgres + Auth), whose client is lazy-loaded so guests never download it · PGlite for database tests · Chakra Petch + JetBrains Mono (self-hosted). Static SPA on Vercel.
Requires Node 20+.
npm install
npm run dev # http://localhost:5173
npm test # 86 tests: engine, database authorization, sync, migration, runtime
npm run typecheck # strict TypeScript
npm run build # typecheck + production build → dist/
Without environment variables the app runs guest-only, which is perfect for working on the game itself. To enable accounts locally, create .env.local:
VITE_SUPABASE_URL=https://<project-ref>.supabase.co
VITE_SUPABASE_ANON_KEY=<publishable anon key>
Both values are public. Never put the service-role key or a database password in a VITE_ variable: anything with that prefix ships to the browser.
In development, the browser console exposes lifeos (the runtime) and lifeosSeed(), which loads about two weeks of demo history ending five days ago so you can see the comeback flow.
The schema lives in supabase/migrations/. Apply it to a Supabase project with the Supabase CLI (supabase db push) or by running the SQL in the dashboard's SQL editor. For email sign-in codes, the Magic Link email template must include {{ .Token }} (the 6-digit code). The link in the email also works when it's opened in the same browser.
Vercel builds on every push to main. The production environment needs VITE_SUPABASE_URL and VITE_SUPABASE_ANON_KEY. vercel.json sets the Vite build, the SPA fallback, immutable caching for hashed assets, and the security headers. Routes are hash-based (/#/chronicle), so refreshing any page is safe.
v0.2: one world, every device. Accounts, cloud saves, cross-device sync, offline play and guest → account migration are in, on top of the v0.1 game (Character, quests, campaigns, achievements, Game Master, Chronicle, reward ceremonies). Phones (iPhone 13 at 390×844) and desktop are both first-class targets.
supabase/templates/. Until then, the default email contains a sign-in link, which works when opened in the same browser the game runs in.The guiding question for every feature: does this make real life more rewarding to engage with? If it only adds bookkeeping, it doesn't ship.