Free, unofficial tool to rank every unit in a Singapore HDB BTO project by your own priorities: floor, facing, block, MRT distance and more. Shortlist your best units.
翻譯準備中
生活風格JavaScript · PythonGitHub @dheemanthlbharadwaj-cloud上線中營運者未確認
試用過了嗎? 點一下就好,不需要登入。
尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證製作者的介紹僅有上面的一句話。 更多詳情請閱讀儲存庫 README。 儲存庫 README ↗
正在載入完整 README。
檢視完整 README ↗Live: https://mybto.sg (the old address mybto.web.app redirects here)
Ranks every sale unit of the June 2026 BTO projects by each user's own importance weights.
| Type | Projects |
|---|---|
| Plus | Kebun Baru Breeze, Kebun Baru Ridge (Ang Mo Kio) |
| Prime | Berlayar Rise (Bukit Merah), Lakeview Cascadia (Bishan) |
| Standard | Sembawang Brook, Sembawang Portico (Sembawang), Woodgrove Acres (Woodlands) |
Stack: a static site on Firebase Hosting (public/, free Spark plan, no Cloud Functions, no sign-in) at https://mybto.sg (mybto.web.app redirects to it).
Rankings and shortlists are stored in a Google Sheet through a Google Apps Script web app (apps-script/, free). The Analytics page
reads combined results from the same web app. The browser knows the web app's address from public/js/config.js (SHEETS_URL).
pipeline/raw/real/, published by python3 pipeline/build_real_data.py --publish)The notes below describe the older sample pipeline.
public/data/units/*.json is generated by python3 pipeline/make_sample_data.py.
Berlayar Rise's unit list (blocks, storeys, unit numbers, flat types, 1,976 units) is real; every other attribute,
and all units of the other six projects, are placeholders.pipeline/raw/facilities_1st_storey.json, read off the HDB brochures); other facility values are placeholders.mscp_m, mscp_near = within 100 m) uses the real car park blocks and block numbers from the
brochure site plans, but the distances are by-eye estimates (about 10 m, 20 m for Sembawang Brook), in
pipeline/raw/mscp_distance.json (with the pixel positions used). wind_open (no block within 30 m on the SE to E side) is a
placeholder correlated with facing in the sample data; build_dataset.py computes it from site-plan stack positions.public/data/sample_submissions.json (420 sample users, npm run sample) is copied into the sheet's "Sample" tab by
importSample() and mixed into Analytics so the charts have something to show. Turn off by setting cell B1 of the "Settings" tab to FALSE.pipeline/build_dataset.py) builds the same JSON plus the Excel workbook
(tabs Plus / Prime / Standard) from the reconciled brochure extractions in pipeline/raw/./ ranking (same as /rank) · /shortlist · /archive/analytics (Analytics is archived: /analytics and /analysis redirect to /, the tab and button come back with ANALYTICS_ENABLED: true in public/js/config.js; ads are off with ADS_ENABLED: false) · /archive/home (old home page). /account, /archive/account and /archive/dashboard redirect to / (see firebase.json).
Inner pages are generated from one shell: edit pipeline/build_pages.py, then python3 pipeline/build_pages.py.
Images in public/img/ are artist's impressions from HDB's June 2026 BTO brochures (© HDB), credited in the footer.
mybto:uid). The last filters and weights per project stay in the browser (mybto:last:<project>).
The ad and the rewarded video are placeholders in public/js/ads.js (one place to plug in a real ad network).SHEETS_URL is set it says "Analytics will appear here soon."firebase.json sends a strict CSP and the usual security headers. Chart.js (archived Analytics only) loads with SRI. No Firebase JS runs on the site.robots.txt and sitemap.xml let search engines list the pages but not /data/. Steps to get into Google: docs/GOOGLE_INDEXING.md.apps-script/; re-paste and publish a new version to apply them.Google Analytics 4 (GA_ID in public/js/config.js, loader public/js/ga.js, live site only) counts visits and the actions rank, shortlist add/remove, share, legend and coffee click. See analytics.google.com.
Google AdSense Auto ads (ADSENSE_CLIENT in public/js/config.js, loader public/js/adsense.js, public/ads.txt, privacy policy at /privacy). Placement is controlled in the AdSense dashboard.
Follow apps-script/README.md. At the end you have an address ending in /exec. Put it in public/js/config.js as SHEETS_URL.
mybto-ce84f, set in .firebaserc; Hosting uses the extra site mybto (mybto.web.app, with the custom domain mybto.sg on top).mybto so the default address is https://mybto.web.app (otherwise change the name in the Apps Script SAMPLE_URL).npx firebase-tools login, then npx firebase-tools hosting:sites:create mybto --project mybto-ce84f (once), then npx firebase-tools deploy --only hosting:site.The old Vercel site and the old Firestore project are no longer used by the code.
npm install # no runtime dependencies; this only sets up the lockfile
npm run dev # http://localhost:3000, static site; SHEETS_URL in js/config.js decides where rankings go
npm run dev:fake # same, with a fake in-memory Google Sheet at /fake-sheets (what the browser test uses)
npm test # unit tests (scoring + analytics maths from apps-script/Analytics.js)
CHROMIUM=/opt/pw-browsers/chromium node test/e2e.browser.js # browser test of the full flow (needs Playwright)