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.
翻譯準備中
透過兩兩比較對任何事物進行排名:挑選兩者中較佳者,一次次對決,排名自行生成。文字、圖像或顏色皆可。免費,無需帳號。
AI 翻譯
Rank anything by pairwise comparison: pick the better of two, duel after duel, and the ranking builds itself. Text, images or colors. Free, no account.
生產力TypeScript · CSSGitHub @CostardRouge上線中營運者未確認
試用過了嗎? 點一下就好,不需要登入。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
Rank anything by comparing two items at a time. Add text, images or colors, pick your favorite in each duel (buttons, keyboard or swipe), and let the ranking emerge. Live: https://versus.steevepommier.com/ (en français; the app itself is at /app/), also on https://costardrouge.github.io/versus/, without publishing檢視完整 README ↗
Rank anything by comparing two items at a time. Add text, images or colors, pick your favorite in each duel (buttons, keyboard or swipe), and let the ranking emerge.
Live: https://versus.steevepommier.com/ (en français; the app itself is at /app/), also on https://costardrouge.github.io/versus/, without publishing
← A, → B, ↓ tie, S skip, ⌘/Ctrl+Z undo) or swipe.| Method | Algorithm | Best for |
|---|---|---|
| Balanced (default) | Bradley-Terry, fitted on all duels at once, with a ± margin per item | Photos, products, anything that doesn't change |
| Dynamic | Elo, duel by duel | Preferences that evolve over time |
| Simple | Smoothed win rate | Readability |
| Exact sort | Binary insertion sort | Settling a short list in the fewest duels |
llms.txt, all generated from one file (see docs/seo.md).docs/pwa.md).localStorage); only what you publish is sent. Visits are counted with a self-hosted, cookie-free Umami, never loaded for visitors who decline (a switch on the legal notice, Do Not Track, Global Privacy Control), and never with a ranking's content or id (see docs/analytics.md).docs/published-boards.md.docs/published-boards.md#notifications)./admin/ lists boards with their reports, hides or features them, removes items and takes boards down (see docs/published-boards.md#moderation)./t/<slug>/, /fr/t/<slug>/) listed in the sitemap once it has a crowd; the gallery's Popular section shows them with the boards the publisher put forward, to vote or start one's own ranking from.Requires Node.js 22 or newer; the project is developed and built on Node 26 (see .nvmrc).
npm install
npm run dev # local server with hot reload
npm run check # lint, typecheck, tests, build: what CI runs
| Script | What it does |
|---|---|
npm run dev | Vite dev server |
npm run build | Production build into dist/ |
npm run preview | Serve the production build |
npm test / npm run test:watch | Unit tests (Vitest) |
npm run coverage | Tests with coverage; the scoring engine must stay above 90% |
npm run e2e | End-to-end tests in Chromium (Playwright): duels by keyboard and swipe, the items list, the color editor, a published board voted to the end |
npm run lint / npm run format | Biome lint and format check / auto-fix |
npm run typecheck | TypeScript in strict mode (app and Worker) |
npm run worker:dev | The whole app and the published boards API on http://localhost:8787 (npm run dev proxies /api to it) |
npm run worker:deploy | Build, deploy to Cloudflare and apply the D1 migrations (needs a Cloudflare account) |
npm run icons | Redraw the favicons, app icons and social card into public/ from build/site.ts |
npm run screenshots | Take the install dialog's screenshots of the app into public/ (needs Playwright's Chromium: npx playwright install chromium, or CHROMIUM_PATH) |
npm run e2e | End-to-end tests: Playwright's Chromium against the app and the Worker run locally (npx playwright install chromium once, or CHROMIUM_PATH) |
npm run vapid | Print a key pair for notifications, to set as the Worker's secrets VAPID_PUBLIC_KEY and VAPID_PRIVATE_KEY |
src/
core/ pure, framework-free logic (fully unit tested)
scoring.ts Bradley-Terry, Elo, win rate, exact sort, pair selection
colors.ts hex/HSL conversions, gradients, harmonies
demos.ts demo data and deterministic simulation
board.ts published boards: votes, visibility, pair assignment
protocol.ts messages and views shared by the app and the Worker
i18n/ en.ts (source of keys), fr.ts (type-checked against en), helpers; landing-*.ts for the home page
landing/ the home page, rendered at build time in each language, then animated
admin/ the publisher's moderation page (/admin/), client of the Worker's admin routes
app/
ui.ts mount(): the entry point
gallery.ts, workspace.ts, items.ts, duel.ts, results.ts, color.ts one module per view
publish.ts, board.ts, remote.ts publishing, the published board page, the API client
rankings.ts navigation and actions on whole rankings
events.ts delegated event listeners
state.ts, dom.ts, header.ts, format.ts, storage.ts shared state, DOM helpers, header, formatting, localStorage
styles.css
build/ build-time SEO: site facts, head tags, JSON-LD, manifest, robots, sitemap, llms.txt (docs/seo.md)
scripts/ icons.ts: icons and social card
worker/ Cloudflare Worker: the site, the API, one Durable Object per published board
tests/ Vitest suites (core, jsdom views, the Worker in workerd) and Playwright end-to-end tests (tests/e2e)
worker/ serves the app and the API for shared boards: each published board is a Durable Object with its own SQLite storage and WebSockets, a D1 registry backs the admin API, and per-IP limits and Turnstile guard publishing. The rules live in src/core/board.ts, shared with the app. It runs locally (npm run worker:dev), in the tests, and live at versus.steevepommier.com; CI deploys it, see docs/online-architecture.md.
.github/workflows/ci.yml runs on every pull request and push to main: Biome, TypeScript, Vitest with coverage, a production build, and the Playwright end-to-end tests (the app with a faked API, and against the real Worker). On main, once both pass, the build is deployed to GitHub Pages, and the Worker (app + API) to Cloudflare once the repository has the CLOUDFLARE_ACCOUNT_ID variable and the CLOUDFLARE_API_TOKEN secret (setup). Dependabot keeps npm packages and actions up to date.
The Pages source must be set once to GitHub Actions in Settings → Pages.
CLAUDE.md: working memory for Claude Code (conventions, code map, domain rules).docs/decisions.md: decision log.docs/roadmap.md: done, next, later, open questions.docs/published-boards.md: agreed behavior of published (shared) boards.docs/online-architecture.md: backend for published boards on Cloudflare (worker/), and how to deploy it.The texts are typed against English, so TypeScript flags a missing key; the language lists are not, so each needs it:
src/i18n/fr.ts and translate it; register it in src/i18n/index.ts (LANGS, MESSAGES, PLURALS); add its button to the language switcher in app/index.html; add its labels to the demos (src/core/demos.ts).src/i18n/landing-*.ts and legal-*.ts, the page shells (copy fr/index.html and fr/mentions-legales/index.html), the language lists in src/landing/ (markup.ts, frame.ts, sections.ts) and src/legal/mount.ts.build/site.ts (LANGUAGES, the pages, titles, descriptions, social cards, LOCALES), then npm run icons for its social card.BoardLang in src/core/types.ts, its use in src/core/board.ts, the templates (src/core/templates.ts, TEMPLATE_LANGS), the Worker's texts (src/i18n/unfurl.ts) and routes (worker/src/index.ts, worker/src/templates.ts).src/i18n/admin.ts and src/admin/admin.ts.grep -rn "'fr'" src build worker/src lists the places that name a language.
MIT © 2026 Steeve Pommier