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。 以下為已儲存的摘錄。
IRCC Tracker for Canada immigration applicants. Calculate your CRS score, follow live IRCC draws, view trends, and get push alerts when new draws are published.
No accounts. No self-hosted backend. Profile data stays on your device.檢視完整 README ↗IRCC Tracker for Canada immigration applicants. Calculate your CRS score, follow live IRCC draws, view trends, and get push alerts when new draws are published.
No accounts. No self-hosted backend. Profile data stays on your device.
All calculators are estimates for planning — each screen points to the official IRCC/provincial tool. Profile data stays on-device.
| Feature | Source |
|---|---|
| Draws (app) | Mobile app → IRCC JSON feed |
| Draws (worker) | Cloudflare Worker → GitHub Actions mirror (data/latest-draw.json)¹ |
| Processing times | Mobile app → GitHub Actions mirror (data/processing-times.json), 7-day cache |
| EE pool / levels | Mobile app → GitHub Actions mirror (data/ee-pool.json), 7-day cache |
| Trends & analytics | Computed on-device from cached draws + EE pool data |
| Push alerts | Cloudflare Worker → Expo Push API |
| Premium unlock | Google Play Billing (one-time managed product: crs_pulse.analytics_unlock) |
¹ canada.ca (Akamai) rejects Cloudflare Worker egress with HTTP 520, so the worker reads the latest draw from a GitHub-hosted mirror instead of IRCC directly.
mobile/ Expo React Native app
workers/push/ Cloudflare Worker (KV + cron)
data/ GitHub Actions mirrors (draws, processing times, EE pool)
docs/ Privacy policy
npm install -g eas-clicd mobile
npm install
cp .env.example .env.local
npm start
Set in mobile/.env.local:
EXPO_PUBLIC_PUSH_URL=https://crs-pulse-push.balwinderxcode.workers.dev
Set your EAS project ID in mobile/.env.local (or EAS secrets):
EAS_PROJECT_ID=your-eas-project-id
Privacy policy — rendered from docs/PRIVACY_POLICY.md and hosted on Vercel (see web/). Use this URL in the stores:
https://www.crspulse.com/privacy
Run on a device or simulator:
npm run ios
Push notifications require a physical iPhone (not simulator).
The worker stores anonymous Expo push tokens and notifies subscribers when IRCC publishes a new draw.
cd workers/push
npm install
npx wrangler login
# Create KV namespaces (one-time)
npx wrangler kv namespace create TOKENS_KV
npx wrangler kv namespace create TOKENS_KV --preview
Paste the returned IDs into workers/push/wrangler.toml, then:
npm run deploy
# Required production secrets (one-time)
npx wrangler secret put PUSH_API_SECRET
npx wrangler secret put SYNC_SECRET
# Optional: ops alerting — the cron emails ALERT_EMAIL once if the draw mirror
# goes >30 days stale (e.g. the GitHub Action stopped). Needs RESEND_API_KEY +
# EMAIL_FROM set too; no-op if unset.
npx wrangler secret put ALERT_EMAIL
Set the same PUSH_API_SECRET value as EXPO_PUBLIC_PUSH_API_KEY in EAS secrets / mobile/.env.local.
Verify:
curl https://crs-pulse-push.balwinderxcode.workers.dev/health
| Method | Path | Auth | Body |
|---|---|---|---|
| GET | /health | None | — |
| POST | /register | Bearer PUSH_API_SECRET | { "token": "ExponentPushToken[...]", "platform": "ios" | "android" } |
| DELETE | /revoke | Bearer PUSH_API_SECRET | { "token": "ExponentPushToken[...]" } |
| POST | /sync | Bearer SYNC_SECRET | — |
Cron runs every 15 minutes after deploy.
Local dev: npm run dev → http://localhost:8787
mobile/)| Command | Description |
|---|---|
npm start | Start Expo dev server |
npm run ios | Run on iOS simulator |
npm run android | Run on Android emulator |
npm test | Run Jest tests |
npm run test:coverage | Run Jest with coverage thresholds |
npm run type-check | TypeScript check |
npm run lint | ESLint |
workers/push/)| Command | Description |
|---|---|
npm run dev | Local worker at :8787 |
npm run deploy | Deploy to Cloudflare |
npm run type-check | TypeScript check |
npm install -g eas-clihttps://www.crspulse.com/privacycd mobile
npm install
cp .env.example .env.local
eas login
eas init # links project, sets EAS_PROJECT_ID
Set in mobile/.env.local:
EAS_PROJECT_ID=your-eas-project-id
EXPO_PUBLIC_PUSH_URL=https://crs-pulse-push.balwinderxcode.workers.dev
com.crspulse.apphttps://www.crspulse.com/privacyITSAppUsesNonExemptEncryption is false)EAS manages APNs credentials. On first iOS production build:
eas credentials --platform ios
Choose Push Notifications: Manage your Apple Push Notifications Key and let EAS create/upload the key.
cd mobile
npm run build:ios # eas build --platform ios --profile production
npm run submit:ios # eas submit --platform ios --profile production --latest
First eas submit will prompt for ascAppId and appleTeamId if not in eas.json.
After the app is live, add to .env.local for the in-app review link:
EXPO_PUBLIC_APP_STORE_ID=1234567890
Production builds with distribution: store go to App Store Connect automatically after submit. Add internal/external testers in TestFlight before submitting for App Review.
EXPO_PUBLIC_PUSH_URL is set in mobile/eas.json for preview and production profiles.
See docs/RELEASE_CHECKLIST.md for the full pre-flight list (push key, FCM V1, data-safety form). Highlights:
Production Android builds are app bundles signed with the upload keystore from local credentials (mobile/credentials.json → credentials/upload-keystore.jks, both gitignored). EAS injects that signing config — a plain gradlew bundleRelease is debug-signed and Play rejects it, so always build through EAS:
cd mobile
npm run build:android # cloud build (recommended)
# or a local build (needs the Android SDK on PATH):
export ANDROID_HOME=$HOME/Library/Android/sdk
eas build --local --platform android --profile production --output build/app.aab
versionCode uses appVersionSource: "remote" + autoIncrement — EAS owns the counter and ignores the value in app.config.js; each build bumps it.
The free tier ships Google AdMob, so the app declares com.google.android.gms.permission.AD_ID (in app.config.js) and the Play Console Advertising ID declaration must be "Yes." ⚠️ The "an active artifact doesn't include AD_ID" error checks every active artifact across all tracks — an old build made before the permission was added keeps tripping it until you roll a compliant build over it / retire that version code. It is not about your newest bundle.
eas submit --platform android --profile production --latest # cloud build
eas submit --platform android --profile production --path build/app.aab # local build
eas submit uses mobile/google-play-service-account.json (gitignored, track internal). That service account must be granted access in Play Console → Users and permissions with at least "Release apps to testing tracks", or submit fails with "the service account is missing the necessary permissions." The first release of a new app must be created manually in the console UI. With permission granted you can also drive a track rollout directly via the Google Play Developer API (edits.insert → tracks.update → edits.commit).
PUSH_API_SECRET must exactly equal the build's EXPO_PUBLIC_PUSH_API_KEY (sent as a Bearer token; mismatch → HTTP 401, surfaced as this message). The key comes from the EAS production environment at build time — keep it in sync with the worker secret.npm run android) to confirm with Google test ads, which always fill.express-entry-calculator/
├── mobile/
│ ├── src/
│ │ ├── features/ # home, dashboard, calculators, fsw, bcpnp, sinp,
│ │ │ # draws, analytics, timeline, tracker, checklist,
│ │ │ # notifications, paywall, profile, onboarding, faq, support
│ │ ├── store/ # Zustand stores (profile, draws, timeline, application,
│ │ │ # premium, processingTimes, eePool)
│ │ ├── services/ # pushService, iapService, errorReporter
│ │ ├── components/ # shared UI (Card, Button, Badge, Input, SkeletonCard, etc.)
│ │ ├── hooks/ # useColors, useAccentColor, useTabBarLayout, etc.
│ │ ├── theme/ # colors, spacing, typography, shadows
│ │ ├── navigation/ # RootNavigator, MainNavigator
│ │ ├── types/ # TypeScript types (Draw, Category, RootStackParamList, etc.)
│ │ └── constants/ # STORAGE_KEYS, IAP_PRODUCTS, CATEGORY_LABELS, etc.
│ └── app.config.js
├── workers/push/
│ └── src/
│ ├── index.ts # HTTP handlers + scheduled cron entry point
│ ├── tokenStore.ts # KV token storage (register/revoke/list/migrate)
│ ├── expoValidate.ts # Token validation against Expo API
│ └── expoReceipts.ts # Async delivery receipt polling
├── data/
│ ├── latest-draw.json # GitHub Actions mirror → worker reads this
│ ├── processing-times.json # IRCC processing times mirror
│ └── ee-pool.json # Express Entry pool + levels plan mirror
└── docs/
└── PRIVACY_POLICY.md
All CRS inputs and profile settings are stored locally on the device. The push worker only stores anonymous Expo device tokens — no personal immigration data is sent to any server. The in-app purchase is processed entirely by Google Play; no payment data reaches us. The free version shows Google AdMob banner ads (which may collect device/ad identifiers); the one-time Premium unlock removes them.
Private project.