TreeMap
무료 오픈소스 디스크 사용량 시각화 도구로, 사각형 트리맵·중복 파일 탐색·디스크 가득 예측·정리 시 파일을 휴지통으로만 이동한다
아직 감지된 업데이트가 없습니다. GitHub 릴리스가 나오면 여기에 보입니다.
개인 계정의 공개 저장소 소유자는 GitHub로 로그인해 운영자를 확인하고 소개를 직접 관리할 수 있습니다. 관리자 승인은 필요하지 않습니다.
로그인한 뒤 확인 파일을 만들어 이 저장소의 기본 브랜치에 30분 안에 커밋해 주세요. 다른 브랜치나 포크의 파일은 인정하지 않습니다. 파일을 올린 뒤 아래에서 확인하면 관리자 승인 없이 관리할 수 있습니다. 자격을 유지하려면 파일을 남겨 두세요.
로그인이 필요하면 로그인 화면으로 이동합니다. 로그인 후 이곳으로 돌아와 원하는 확인 버튼을 다시 눌러 주세요.
프로젝트 폴더에서 /nomorevibe verify를 실행하면 소유권을 확인하고 소개를 직접 관리할 수 있습니다.
1분 만에 확인하기This is an own personal tracker to track my progress in work
저장소 README에서 가져옴
README 전체를 불러오는 중입니다. 아래는 저장된 발췌입니다.
A personal task-management and time-tracking app. Google Sheets is the
database; this Next.js app is the UI on top of it — plan your day, prioritize
by effort vs. impact, track time down to the second, and see where your time
actually went.
You can type a task straight into the spreadsheet with nothing but a title —
the app fills in an id, status, priority, category and timestamps the next
time it loads, and writes them back to the sheet.
Quick start (no Google account needed yet)README 전문 보기 ↗A personal task-management and time-tracking app. Google Sheets is the database; this Next.js app is the UI on top of it — plan your day, prioritize by effort vs. impact, track time down to the second, and see where your time actually went.
You can type a task straight into the spreadsheet with nothing but a title — the app fills in an id, status, priority, category and timestamps the next time it loads, and writes them back to the sheet.
npm install
npm run dev
Open http://localhost:3000. With no Google credentials configured, the app
automatically falls back to a local JSON file at data/local-db.json — fully
functional, just not synced to a spreadsheet. Settings → Storage shows which
mode you're in.
Create a spreadsheet. Any blank Google Sheet works — the app creates
all 13 tabs (Tasks, Subtasks, TimeEntries, DailyPlan, WeeklyPlan,
TaskHistory, Categories, Priorities, Statuses, ActivityTags,
DashboardData, Reports, Settings) and seeds sensible defaults the first
time it connects. Copy the spreadsheet id out of its URL:
https://docs.google.com/spreadsheets/d/THIS_PART/edit.
Create a service account (this is how the app authenticates — there's no interactive Google login):
Share the spreadsheet with the service account. Open the JSON key
file and copy the client_email field (looks like
[email protected]). In your Google Sheet,
click Share and give that email address Editor access.
Configure the app. Copy .env.example to .env and fill in:
STORAGE_DRIVER=sheets
GOOGLE_SHEETS_SPREADSHEET_ID=<the id from step 1>
GOOGLE_APPLICATION_CREDENTIALS=./credentials/service-account.json
Put the downloaded JSON key at that path (the credentials/ folder is
git-ignored). If you'd rather not keep a key file around, you can instead
set GOOGLE_SERVICE_ACCOUNT_EMAIL and GOOGLE_PRIVATE_KEY directly —
see the comments in .env.example.
Initialize and run:
npm run sheets:init # creates tabs/headers and seeds defaults — optional,
# the app does this automatically on first request too
npm run dev
Settings → Storage should now show "Google Sheets" with a link to open the spreadsheet.
The Tasks tab is the one place designed for quick manual entry — type a
title into the Task column (or its header can just say Task or Point)
and leave everything else blank. The app claims that row on its next load:
assigns an id, Yet to Start status, Medium priority, your default
category/type, and a created timestamp, then writes those back so the row
becomes a fully-fledged task. Everything else — priority, effort/impact,
planning, time tracking, subtasks, notes — is meant to be managed from the
UI, though the sheet is never off-limits: edit a cell by hand and it'll be
picked up (and, for dates/numbers, is read back correctly whether Sheets
stored it as text or as a real date/number cell).
| Command | What it does |
|---|---|
npm run dev | Start the dev server (http://localhost:3000) |
npm run build | Production build |
npm run start | Run the production build |
npm run typecheck | tsc --noEmit |
npm test | Run the unit/integration test suite (Vitest) |
npm run sheets:init | Ensure tabs/headers/defaults exist in the configured spreadsheet |
src/lib/schema.ts — the canonical spreadsheet schema (every tab,
every column, and the header aliases that let a hand-typed Task column
map onto the real field).src/lib/storage/ — the storage layer. sheets.ts talks to the
Google Sheets API; local.ts is the JSON-file fallback. Both implement
the same row-level StorageDriver interface, so nothing above this layer
knows or cares which one is active. Every mutation is serialized through
an in-process queue so a double-click can't interleave two writes.src/lib/domain/ — pure logic with no I/O: the timer state machine
(derives running/accumulated time from stored entries, not a client
accumulator, so a refresh can never lose it), effort/impact quadrant
classification, the "what should I work on" scoring, concurrency-safe
time aggregation, and daily-plan math.src/lib/repo/ — typed CRUD and business rules on top of storage:
task/subtask/timer/plan/settings/lookup operations, all timer actions
keyed by a client-generated opId so retries and offline replays can
never create a duplicate entry or double-count time.src/app/api/ — thin Next.js route handlers that validate input and
delegate to repo/.src/app/*/page.tsx — the eight primary views (Dashboard, Task List,
Task Detail, Quadrant, Daily/Weekly Planner, Time Tracker, Reports,
Settings), plus src/components/ and src/lib/client/ for the shared UI
kit, the offline-safe API client, and snapshot polling.TimeEntries, and the UI always
recomputes elapsed time from that row's checkIn plus the sum of earlier
closed entries. Refresh, navigate away, close the tab — the timer is
exactly where it left off because it was never anywhere else.opId). If a
request is retried (a flaky connection, a double click, an offline queue
replay), the server recognizes the same opId and returns the existing
result instead of creating a second entry.localStorage with its opId intact and replayed in order the
next time the app is online — never dropped, never duplicated.