TreeMap
무료 오픈소스 디스크 사용량 시각화 도구로, 사각형 트리맵·중복 파일 탐색·디스크 가득 예측·정리 시 파일을 휴지통으로만 이동한다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기AI read-it-later & personal knowledge base
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
Save anything. Keep it in one place.
Purl is a read-it-later app — a home for your "pearls". You paste URLs: web pages, PDFs, YouTube videos, and audio. Purl resolves each item's metadata (title, favicon, description, thumbnail) and keeps everything in one place, available from the app, a REST API, and an MCP server.
Purl is free, with one limit: each account can save up to 1,000 links (MAX_SAVED_LINKS in src/lib/limits.ts).
The product goal: one place to stash material you care about.README 전문 보기 ↗Save the links worth keeping. Share the ones worth passing on.
Live preview: https://purl.live
Purl is a calm place to save and share the links you find — a home for your "pearls". You paste URLs: web pages, PDFs, YouTube videos, and audio. Purl resolves each item's metadata (title, favicon, description, thumbnail) and keeps everything in one place, available from the app, a REST API, and an MCP server.
Purl is free, with one limit: each account can save up to 1,000 links (MAX_SAVED_LINKS in src/lib/limits.ts).
The product goal: one place to keep the links you care about, and an easy way to share the ones worth passing on.
safeFetch with optional proxy/DNS controls (see AGENTS.md). An egress proxy can be configured via SAFE_OUTBOUND_HTTP_PROXY./api/v1 (links and folders) and an MCP server (save_link, list_saved_items, get_link, move_link, list_folders, create_folder, update_folder, delete_folder) with API-key or OAuth auth.src/app/sw.ts) that builds to public/sw.js (generated on pnpm build, gitignored). Enables Install in Chrome/Edge and similar where the platform supports it, with runtime caching via Serwist's Next.js defaults and a static offline shell at /~offline. Serwist is disabled in pnpm dev to avoid service-worker cache surprises during development — use pnpm build && pnpm start (or your production URL) to exercise installability and the SW.Saving a link is fully synchronous — there is no background processing.
POST /api/links with a URL (also /api/v1/links and the MCP save_link tool).detectContentType (SSRF-safe HEAD / sniff) plus scrapeLinkMetadata (Open Graph HTML, PDF Content-Disposition / size, YouTube oEmbed). Saving an existing URL again refreshes its metadata and moves it to the top.Link row with title, favicon, thumbnail, domain, and contentType (WEB, PDF, YOUTUBE, or AUDIO).broadcastLinksChanged notifies other tabs/devices via Supabase Realtime.These are called out explicitly because the repo is going public:
Marketing vs. product: The landing page copy mentions ideas such as collections and a weekly digest. Those are not built in the current schema or app — treat them as roadmap, not shipped features.
@serwist/next), web manifest + precache / offline fallbackAutomation lives under .github/workflows/. Every PR and manual release is gated by these pipelines.
pr-checks.ymlRuns on pull_request to develop and main: Setup & validation → Prisma (generate client + type fixes) → Lint and type check (in parallel) → Tests and production build (in parallel, after lint and type check pass). Concurrency is per-PR so new pushes cancel stale runs.
release.ymlRuns on workflow_dispatch (manual): Merge develop into main, then build validation so production is only promoted after a green build.
Purl is built around untrusted input (arbitrary URLs). A few layers matter in production:
fetch. OG/thumbnail probes, PDF fetch, content-type sniffing, and similar paths go through safeFetch: HTTP(S) only, blocked private/link-local/reserved targets, redirect handling with per-hop host checks, DNS resolution pinned before connect (mitigates classic DNS rebinding against the pre-check), optional response size caps (e.g. PDF proxy). Optional egress proxy and custom DNS servers are documented in AGENTS.md.proxy redirects unauthenticated users away from private routes. Sign-in is OAuth-only (Google/GitHub, plus Apple when configured); there are no passwords./api/links, /api/v1/*, MCP, etc.) resolve the session server-side and scope work to the signed-in user.UPSTASH_REDIS_REST_URL and UPSTASH_REDIS_REST_TOKEN are set, the proxy applies per-IP limits to /api/auth/*, POST /api/links, and POST /api/feedback (see proxy-rate-limit.ts). Without Upstash, limits are disabled — fine locally, not ideal for production.SUPABASE_SECRET_KEY (or the legacy SUPABASE_SERVICE_ROLE_KEY) and similar values are server-only. The browser uses the Supabase anon key for Realtime only; .env stays gitignored.safe-outbound-fetch).Reporting a vulnerability: use GitHub Security Advisories for this repository so details stay private until patched.
pnpm (this repo includes pnpm-lock.yaml)pnpm install
Create a .env file in the repo root. See .env.example for the full list; minimum for core behavior:
DATABASE_URL="postgresql://USER:PASSWORD@HOST:5432/DBNAME"
# Supabase Realtime — cross-device instant link list sync (same project as Postgres)
SUPABASE_URL="https://YOUR_PROJECT.supabase.co"
SUPABASE_ANON_KEY="eyJ..."
SUPABASE_SECRET_KEY="sb_secret_..."
# Sign-in (OAuth apps with callback {BETTER_AUTH_URL}/api/auth/callback/{google,github})
GOOGLE_CLIENT_ID="..."
GOOGLE_CLIENT_SECRET="..."
GITHUB_CLIENT_ID="..."
GITHUB_CLIENT_SECRET="..."
# Optional (used to send in-app feedback emails)
RESEND_API_KEY="re_..."
RESEND_FROM="Purl <[email protected]>"
Notes:
DATABASE_URL is required (Prisma + Better Auth).http://localhost:3000/api/auth/callback/{google,github}. Apple is optional and enabled only when all four APPLE_* vars are set (see .env.example).RESEND_API_KEY, in-app feedback can't be sent..env.example — copy those keys for a working auth setup.pnpm prisma migrate dev
pnpm prisma generate
pnpm dev
Open http://localhost:3000.
Optional: a named HTTPS URL with portless. With portless installed globally (npm install -g portless, Node.js 24+), run portless run instead of pnpm dev. It runs the dev script behind a local proxy at https://purl.localhost. Point auth at that URL in .env.local, or sign-in rejects the origin:
BETTER_AUTH_URL="https://purl.localhost"
BASE_URL="https://purl.localhost"
In a git worktree, portless prefixes the branch name (for example https://my-branch.purl.localhost); set both variables to that URL there.
PWA / install: With pnpm dev, the service worker is not active. After a production build, public/sw.js exists locally; run pnpm start and open the app in Chromium to use Install or to test offline navigation to /~offline.
Tests use Vitest and focus on critical logic (formatters, link grouping, auth routing, API behavior, metadata scraping). They intentionally avoid shallow UI-only wrappers.
pnpm test # run once
pnpm test:watch # watch mode
pnpm lint
pnpm build
pnpm start
pnpm test
More contributor notes (Prisma, outbound proxy env): see AGENTS.md.