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,即可驗證所有權並自行管理介紹。
一分鐘完成驗證Cover your network. A private networking tracker and call calendar for students recruiting for internships.
翻譯準備中
取自儲存庫 README
正在載入完整 README。
檢視完整 README ↗Coverage is a list for your recruiting season: every banker, alum, and recruiter you’re talking to, where each conversation stands, and the calls on your calendar.
Cover your network. A private networking tracker for college students recruiting for internships: a spreadsheet-style contact grid plus a weekly call calendar.
Live demo: https://coverage-green.vercel.app · sign up free, then click Try with example data.
| Import from LinkedIn, with a review step | Book calls on a weekly calendar |
|---|---|
Connections.csv from LinkedIn's data export (or any tracker CSV), or paste profile URLs. Every
import goes through an editable review table that skips duplicates.All free tiers; no paid APIs.
| Layer | Choice |
|---|---|
| Framework | Next.js 16 (App Router, Cache Components) · React 19 · TypeScript |
| Styling | Tailwind CSS v4 with design tokens · IBM Plex Sans/Mono + Source Serif 4 |
| Auth + database | Supabase: Auth (email, Google OAuth) and Postgres with Row Level Security |
| Calendar | FullCalendar v6 (MIT core: timeGrid + interaction) |
| PDF parsing | pdf.js (pdfjs-dist), lazy-loaded, runs in the browser |
| Testing | Vitest (unit + RLS isolation) · Playwright + axe-core (end-to-end + accessibility) |
| CI / hosting | GitHub Actions · Vercel Hobby |
flowchart LR
subgraph Browser
UI["React UI<br/>Contacts grid · Calendar · Import"]
PDF["pdf.js<br/>(profile PDFs never leave the browser)"]
SBC["Supabase JS client<br/>(publishable key only)"]
UI --> PDF
UI --> SBC
end
subgraph Vercel["Vercel (Next.js)"]
PX["proxy.ts<br/>refresh session cookie,<br/>guard /contacts /calls /account"]
RH["Route handlers<br/>/auth/callback · /auth/confirm · /auth/signout"]
RSC["Server Components<br/>(read the signed-in user)"]
end
subgraph Supabase
AUTH["Auth<br/>email + Google"]
PG[("Postgres<br/>profiles · contacts · calls<br/>Row Level Security")]
end
Google["Google OAuth"]
UI -- page requests --> PX
PX --> RSC
SBC -- "queries with the user's JWT" --> PG
SBC --> AUTH
RH --> AUTH
AUTH <--> Google
RSC --> PG
Most reads and writes go directly from the browser to Postgres with the user's session token. There is no custom API layer to secure: the database decides what each request may see.
| Table | Columns |
|---|---|
profiles | id → auth.users, full_name, created_at (created by a trigger on sign-up) |
contacts | id, user_id, company, name, title, stage (contacted | call_scheduled | called), follow_up_date, notes, linkedin_url, is_example, created_at, updated_at |
calls | id, user_id, contact_id → contacts, starts_at, duration_minutes (default 30) |
contact_notes | contact_id → contacts (one per contact), user_id, doc (JSON notes document), updated_at |
contacts also has an optional email. contacts.notes holds a plain-text copy of the notes document so the grid
preview, search, and CSV export never need to load every document.
Every foreign key to auth.users is on delete cascade, so deleting an account removes all of its data. SQL lives in
supabase/migrations.
select / insert / update / delete policies require
auth.uid() = user_id (or = id for profiles). Logged-out requests match no policy. The calls insert/update
policies (and the same policies on contact_notes) also check that the linked contact belongs to the same user, so
you can't attach a call or notes to someone else's contact. (0002_rls.sql)security definer function that can only delete the caller's own
auth.users row. (0003_functions.sql)tests/rls/isolation.test.ts signs in as two ordinary users and
checks that user B can't read, update, delete, or insert into user A's contacts, calls, notes, or profile, and that
logged-out requests see nothing.@supabase/ssr keeps the session in HTTP cookies; proxy.ts validates the JWT (getClaims) on each
request. Server code never trusts an unverified session.?next= values pass through safeNextPath(), which rejects absolute and protocol-relative URLs
(no open redirects). Log out is POST-only.=, +, -, or @ so a malicious name can't run a spreadsheet
formula..env.local is git-ignored; documents every variable.You need Node.js 24+ and a free Supabase project.
git clone https://github.com/tfinn18/coverage.git
cd coverage
npm install
cp .env.example .env.local # add your Supabase URL and publishable key
npm run dev # http://localhost:3000
supabase/migrations/ in order (0001 → 0005).http://localhost:3000/** to Redirect URLs.https://<project-ref>.supabase.co/auth/v1/callback as an authorized redirect URI, and paste the client ID and
secret into Supabase → Authentication → Sign In / Providers → Google.| Command | What it checks |
|---|---|
npm run lint · npm run typecheck | ESLint and TypeScript |
npm test | 60 unit tests: CSV and PDF parsers (with fixture files), import mapping and duplicate detection, sort/filter, follow-up flags, scheduling helpers, Google Calendar links, the notes document (including converting the old layout), list editing, Gmail and mailto links, safe redirects |
npm run test:rls | 8 checks that one user can't touch another's rows, including notes (needs two test accounts in .env.local) |
npm run test:e2e | Playwright: sign in, add a contact, reload, see it on the calendar, delete it; write and reopen notes (Enter/Backspace lists, Copy, Open in Gmail, Escape), notes from the old layout open in the new one; the notes sheet at phone width; plus axe WCAG 2.1 AA scans of 8 pages and the open notes panel in light and dark mode. E2E_BASE_URL=https://coverage-green.vercel.app runs it against production |
GitHub Actions runs lint, typecheck, unit tests, and a production build on every push. The RLS and end-to-end suites need real credentials, so they run locally.
src/
app/ routes: landing, privacy, (auth) pages, (app) pages, auth route handlers
components/ ui primitives, contacts grid, import dialog, calls calendar
lib/ framework-free logic (unit-tested): contacts, csv, pdf, linkedin, import, calls
lib/supabase/ browser client, server client, session proxy
proxy.ts route guard (Next.js 16's name for middleware)
supabase/migrations/ schema, RLS policies, functions
tests/ unit tests, fixtures, RLS isolation test
e2e/ Playwright end-to-end and accessibility tests
A starting point for interviews and resume bullets. Edit it into your own words.
security definer SQL function instead, so no secret key exists in the codebase or on Vercel.CLAUDE.md records the
conventions it followed.Resume bullets (examples):
Supabase's free plan only allows editing the auth email templates once you configure a custom SMTP server, so Coverage uses Supabase's default confirmation and password-reset emails.
Those default emails use the PKCE flow: the link carries a one-time code that can only be exchanged
for a session in the same browser that requested the email (a secret "code verifier" is stored there).
What that means in practice:
How to remove the limitation: add custom SMTP in Supabase (Authentication → Emails → SMTP Settings;
a free tier from a provider like Resend or Brevo works), then change the two templates so their links
use a token_hash, which /auth/confirm already supports on any device:
<!-- Confirm signup -->
<a href="{{ .RedirectTo }}?token_hash={{ .TokenHash }}&type=email">Confirm your email</a>
<!-- Reset password -->
<a href="{{ .RedirectTo }}&token_hash={{ .TokenHash }}&type=recovery">Reset your password</a>
(The reset link uses & because its redirect URL already contains ?next=/reset-password.)
.env.example